From 2bb0009861558e5546ac87d9527d97043cbb6eb5 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 7 Dec 2023 10:43:07 +0100 Subject: [PATCH 001/121] Initial implementation --- include/DiscreteAngle.h | 12 ++++++++++++ include/Range.h | 28 ++++++++++++++++++++++++++++ src/DiscreteAngle.cpp | 24 ++++++++++++++++++++++++ src/Range.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 include/DiscreteAngle.h create mode 100644 include/Range.h create mode 100644 src/DiscreteAngle.cpp create mode 100644 src/Range.cpp diff --git a/include/DiscreteAngle.h b/include/DiscreteAngle.h new file mode 100644 index 0000000..ee2ca31 --- /dev/null +++ b/include/DiscreteAngle.h @@ -0,0 +1,12 @@ +#ifndef DISCRETEANGLE_H +#define DISCRETEANGLE_H + +#include "Range.h" + +// A fixed point 16-bit signed angle between (-180..180] +class DiscreteAngle16 : Range16 { +public: + DiscreteAngle16(float angle); +}; + +#endif \ No newline at end of file diff --git a/include/Range.h b/include/Range.h new file mode 100644 index 0000000..09f7ffc --- /dev/null +++ b/include/Range.h @@ -0,0 +1,28 @@ +#ifndef RANGE_H +#define RANGE_H + +/// @brief Signed range. May be renamed to SignedRange later +class Range16 { +public: + Range16(); + Range16(float range); // range -1..1 + Range16(short range); // range -32768..32767 + + inline Range16 operator-(Range16 a); + inline Range16 operator+(Range16 a); + + inline bool operator==(Range16 a); + inline bool operator!=(Range16 a); + + inline bool operator<(Range16 a); + inline bool operator>(Range16 a); + inline bool operator<=(Range16 a); + inline bool operator>=(Range16 a); + +protected: + // How do we make sure we have 16 bit range on every platform? + // uint16_t range; // 16-bit range + unsigned short range; // 16-bit range +}; + +#endif \ No newline at end of file diff --git a/src/DiscreteAngle.cpp b/src/DiscreteAngle.cpp new file mode 100644 index 0000000..7ab700f --- /dev/null +++ b/src/DiscreteAngle.cpp @@ -0,0 +1,24 @@ +// 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 + +DiscreteAngle16::DiscreteAngle16(float angle) : Range16() { + if (!isfinite(angle)) { + range = 0; + return; + } + + // clamp the float range to -1..1 + while (angle <= -180.0F) + angle += 360.0F; + while (angle > 180.0F) + angle -= 360.0F; + + // map (-180..180] to 1..65535 + // This means that range value 0 is not used + this->range = (unsigned short)((angle + 180.0F) * 65535.0F); +} diff --git a/src/Range.cpp b/src/Range.cpp new file mode 100644 index 0000000..340f165 --- /dev/null +++ b/src/Range.cpp @@ -0,0 +1,38 @@ +#include "Range.h" + +Range16::Range16() { this->range = 0; } + +Range16::Range16(float f) { + // clamp the float range to -1..1 + if (f < -1.0F) + f = -1.0F; + else if (f > 1.0F) + f = 1.0F; + + // map -1..1 to 0..65535 + this->range = (unsigned short)((f + 1.0F) * 65535.0F); +} + +Range16::Range16(short s) { + // clamp the range to -32767..32767 + // This is needed because the representation can support +/-32768 (like 2s + // complement) + if (s < -32767) + s = -32767; + else if (s > 32767) + s = 32767; + + this->range = (unsigned short)(s + 32767); +} + +Range16 Range16::operator-(Range16 a) { this->range - a.range; }; + +Range16 Range16::operator+(Range16 a) { this->range + a.range; }; + +bool Range16::operator==(Range16 a) { return (this->range == a.range); } +bool Range16::operator!=(Range16 a) { return (this->range != a.range); } + +bool Range16::operator<(Range16 a) { return (this->range < a.range); } +bool Range16::operator>(Range16 a) { return (this->range > a.range); } +bool Range16::operator<=(Range16 a) { return (this->range <= a.range); } +bool Range16::operator>=(Range16 a) { return (this->range >= a.range); } \ No newline at end of file From bd04285d48f1a45bc33264c0cc80b6c4e58325e6 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 7 Dec 2023 10:48:47 +0100 Subject: [PATCH 002/121] Make superclass accessable --- include/DiscreteAngle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/DiscreteAngle.h b/include/DiscreteAngle.h index ee2ca31..d5e0c95 100644 --- a/include/DiscreteAngle.h +++ b/include/DiscreteAngle.h @@ -4,7 +4,7 @@ #include "Range.h" // A fixed point 16-bit signed angle between (-180..180] -class DiscreteAngle16 : Range16 { +class DiscreteAngle16 : public Range16 { public: DiscreteAngle16(float angle); }; From 254bb27f53acc26c41080ac5a6d32f3d5d5f3b19 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 7 Dec 2023 10:51:20 +0100 Subject: [PATCH 003/121] Added negation --- include/Range.h | 1 + src/Range.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/Range.h b/include/Range.h index 09f7ffc..8f8834e 100644 --- a/include/Range.h +++ b/include/Range.h @@ -10,6 +10,7 @@ public: inline Range16 operator-(Range16 a); inline Range16 operator+(Range16 a); + inline Range16 operator-(); inline bool operator==(Range16 a); inline bool operator!=(Range16 a); diff --git a/src/Range.cpp b/src/Range.cpp index 340f165..3e3661e 100644 --- a/src/Range.cpp +++ b/src/Range.cpp @@ -26,10 +26,11 @@ Range16::Range16(short s) { } Range16 Range16::operator-(Range16 a) { this->range - a.range; }; - Range16 Range16::operator+(Range16 a) { this->range + a.range; }; -bool Range16::operator==(Range16 a) { return (this->range == a.range); } +Range16 Range16::operator-() { -this->range; } + +bool Range16::operator==(Range16 a) { this->range == a.range; } bool Range16::operator!=(Range16 a) { return (this->range != a.range); } bool Range16::operator<(Range16 a) { return (this->range < a.range); } From de3a6479cf0985362ca0b28acd62189dd2bd75ba Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 7 Dec 2023 10:56:49 +0100 Subject: [PATCH 004/121] Updated negation --- include/Range.h | 2 +- src/Range.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Range.h b/include/Range.h index 8f8834e..f66bcf0 100644 --- a/include/Range.h +++ b/include/Range.h @@ -10,7 +10,7 @@ public: inline Range16 operator-(Range16 a); inline Range16 operator+(Range16 a); - inline Range16 operator-(); + inline Range16 &operator-(); inline bool operator==(Range16 a); inline bool operator!=(Range16 a); diff --git a/src/Range.cpp b/src/Range.cpp index 3e3661e..af23906 100644 --- a/src/Range.cpp +++ b/src/Range.cpp @@ -28,7 +28,7 @@ Range16::Range16(short s) { Range16 Range16::operator-(Range16 a) { this->range - a.range; }; Range16 Range16::operator+(Range16 a) { this->range + a.range; }; -Range16 Range16::operator-() { -this->range; } +Range16 &Range16::operator-() { -this->range; } bool Range16::operator==(Range16 a) { this->range == a.range; } bool Range16::operator!=(Range16 a) { return (this->range != a.range); } From 2b50babcf12a5d30e27cdc1ba0469012dbca3dcc Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 7 Dec 2023 11:03:06 +0100 Subject: [PATCH 005/121] Add negation for DiscreteAngle --- include/DiscreteAngle.h | 2 ++ src/DiscreteAngle.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/DiscreteAngle.h b/include/DiscreteAngle.h index d5e0c95..17c4616 100644 --- a/include/DiscreteAngle.h +++ b/include/DiscreteAngle.h @@ -7,6 +7,8 @@ class DiscreteAngle16 : public Range16 { public: DiscreteAngle16(float angle); + + inline DiscreteAngle16 &operator-(); }; #endif \ No newline at end of file diff --git a/src/DiscreteAngle.cpp b/src/DiscreteAngle.cpp index 7ab700f..9544da1 100644 --- a/src/DiscreteAngle.cpp +++ b/src/DiscreteAngle.cpp @@ -22,3 +22,5 @@ DiscreteAngle16::DiscreteAngle16(float angle) : Range16() { // This means that range value 0 is not used this->range = (unsigned short)((angle + 180.0F) * 65535.0F); } + +DiscreteAngle16 &DiscreteAngle16::operator-() { -this->range; } \ No newline at end of file From 2cbf2594eb7ea5a23962b7e9b465dfaf9993ef3a Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 7 Dec 2023 11:04:03 +0100 Subject: [PATCH 006/121] Make negation virtual override --- include/DiscreteAngle.h | 2 +- include/Range.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/DiscreteAngle.h b/include/DiscreteAngle.h index 17c4616..5a2171b 100644 --- a/include/DiscreteAngle.h +++ b/include/DiscreteAngle.h @@ -8,7 +8,7 @@ class DiscreteAngle16 : public Range16 { public: DiscreteAngle16(float angle); - inline DiscreteAngle16 &operator-(); + inline DiscreteAngle16 &operator-() override; }; #endif \ No newline at end of file diff --git a/include/Range.h b/include/Range.h index f66bcf0..e73cde7 100644 --- a/include/Range.h +++ b/include/Range.h @@ -10,7 +10,7 @@ public: inline Range16 operator-(Range16 a); inline Range16 operator+(Range16 a); - inline Range16 &operator-(); + inline virtual Range16 &operator-(); inline bool operator==(Range16 a); inline bool operator!=(Range16 a); From 3714507059d558c586685e1af286adc20356eb60 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 5 Mar 2024 09:55:07 +0100 Subject: [PATCH 007/121] Implemented templated angles --- DiscreteAngle.cpp | 35 ++++++++++++++++++++++++++++++----- DiscreteAngle.h | 19 ++++++++++++++----- Range.cpp | 4 +++- Range.h | 12 ++++++++++++ 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/DiscreteAngle.cpp b/DiscreteAngle.cpp index 9544da1..2ce3a55 100644 --- a/DiscreteAngle.cpp +++ b/DiscreteAngle.cpp @@ -6,9 +6,9 @@ #include -DiscreteAngle16::DiscreteAngle16(float angle) : Range16() { +template <> AngleUsing::AngleUsing(unsigned char angle) { if (!isfinite(angle)) { - range = 0; + value = 0; return; } @@ -18,9 +18,34 @@ DiscreteAngle16::DiscreteAngle16(float angle) : Range16() { while (angle > 180.0F) angle -= 360.0F; - // map (-180..180] to 1..65535 + // map (-180..180] to 1..256 // This means that range value 0 is not used - this->range = (unsigned short)((angle + 180.0F) * 65535.0F); + this->value = (unsigned char)((angle + 180.0F) * 255.0F); } -DiscreteAngle16 &DiscreteAngle16::operator-() { -this->range; } \ No newline at end of file +template <> float AngleUsing::ToFloat() { + float f = ((float)this->value / 255.0F) - 180.0F; + return f; +} + +template <> AngleUsing::AngleUsing(unsigned short angle) { + if (!isfinite(angle)) { + value = 0; + return; + } + + // clamp the float range to -1..1 + while (angle <= -180.0F) + angle += 360.0F; + while (angle > 180.0F) + angle -= 360.0F; + + // map (-180..180] to 1..256 + // This means that range value 0 is not used + this->value = (unsigned short)((angle + 180.0F) * 65535.0F); +} + +template <> float AngleUsing::ToFloat() { + float f = ((float)this->value / 65535.0F) - 180.0F; + return f; +} \ No newline at end of file diff --git a/DiscreteAngle.h b/DiscreteAngle.h index 5a2171b..f056e7d 100644 --- a/DiscreteAngle.h +++ b/DiscreteAngle.h @@ -4,11 +4,20 @@ #include "Range.h" // A fixed point 16-bit signed angle between (-180..180] -class DiscreteAngle16 : public Range16 { -public: - DiscreteAngle16(float angle); +// class DiscreteAngle16 : public Range16 { +// public: +// DiscreteAngle16(float angle); - inline DiscreteAngle16 &operator-() override; +// inline DiscreteAngle16 &operator-() override; +// }; + +template class AngleUsing : RangeUsing { +public: + AngleUsing(T sourceValue); + float ToFloat(); + inline T GetValue() { return this->value; } }; -#endif \ No newline at end of file +#endif + +template inline float AngleUsing::ToFloat() { return 0.0f; } diff --git a/Range.cpp b/Range.cpp index af23906..15bb7ca 100644 --- a/Range.cpp +++ b/Range.cpp @@ -1,5 +1,6 @@ #include "Range.h" +/* Range16::Range16() { this->range = 0; } Range16::Range16(float f) { @@ -36,4 +37,5 @@ bool Range16::operator!=(Range16 a) { return (this->range != a.range); } bool Range16::operator<(Range16 a) { return (this->range < a.range); } bool Range16::operator>(Range16 a) { return (this->range > a.range); } bool Range16::operator<=(Range16 a) { return (this->range <= a.range); } -bool Range16::operator>=(Range16 a) { return (this->range >= a.range); } \ No newline at end of file +bool Range16::operator>=(Range16 a) { return (this->range >= a.range); } +*/ \ No newline at end of file diff --git a/Range.h b/Range.h index e73cde7..e521c71 100644 --- a/Range.h +++ b/Range.h @@ -1,6 +1,7 @@ #ifndef RANGE_H #define RANGE_H +/* /// @brief Signed range. May be renamed to SignedRange later class Range16 { public: @@ -25,5 +26,16 @@ protected: // uint16_t range; // 16-bit range unsigned short range; // 16-bit range }; +*/ + +template class RangeUsing { +public: + inline RangeUsing operator-(RangeUsing a) { this->value - a.value; } + inline RangeUsing operator+(RangeUsing a) { this->value + a.value; } + inline RangeUsing operator-() { this->value = -this.value; } + inline T GetValue() { return value; } + + T value; +}; #endif \ No newline at end of file From 0468031b4b91f0e106d728eae0f846dee4fb25aa Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 5 Mar 2024 10:00:56 +0100 Subject: [PATCH 008/121] Bug fix --- DiscreteAngle.cpp | 27 +++++++++++---------------- DiscreteAngle.h | 8 +------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/DiscreteAngle.cpp b/DiscreteAngle.cpp index 2ce3a55..0a0e4cd 100644 --- a/DiscreteAngle.cpp +++ b/DiscreteAngle.cpp @@ -4,6 +4,7 @@ #include "DiscreteAngle.h" +#include "Angle.h" #include template <> AngleUsing::AngleUsing(unsigned char angle) { @@ -12,19 +13,16 @@ template <> AngleUsing::AngleUsing(unsigned char angle) { return; } - // clamp the float range to -1..1 - while (angle <= -180.0F) - angle += 360.0F; - while (angle > 180.0F) - angle -= 360.0F; + // normalize to (-180..180] + angle = Angle::Normalize(angle); - // map (-180..180] to 1..256 + // 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) * 255.0F); + this->value = (unsigned char)((angle + 180.0F) / 360.0F * 255.0F); } template <> float AngleUsing::ToFloat() { - float f = ((float)this->value / 255.0F) - 180.0F; + float f = ((float)this->value / 255.0F) * 360.0F - 180.0F; return f; } @@ -34,18 +32,15 @@ template <> AngleUsing::AngleUsing(unsigned short angle) { return; } - // clamp the float range to -1..1 - while (angle <= -180.0F) - angle += 360.0F; - while (angle > 180.0F) - angle -= 360.0F; + // normalize to (-180..180] + angle = Angle::Normalize(angle); - // map (-180..180] to 1..256 + // 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) * 65535.0F); + this->value = (unsigned short)((angle + 180.0F) / 360.0F * 65535.0F); } template <> float AngleUsing::ToFloat() { - float f = ((float)this->value / 65535.0F) - 180.0F; + 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 index f056e7d..0112584 100644 --- a/DiscreteAngle.h +++ b/DiscreteAngle.h @@ -3,13 +3,7 @@ #include "Range.h" -// A fixed point 16-bit signed angle between (-180..180] -// class DiscreteAngle16 : public Range16 { -// public: -// DiscreteAngle16(float angle); - -// inline DiscreteAngle16 &operator-() override; -// }; +// A fixed angle between (-180..180] template class AngleUsing : RangeUsing { public: From 273ebae33b2e6adfd7c07771ab06648c82b09cc2 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 5 Mar 2024 10:17:29 +0100 Subject: [PATCH 009/121] Fixes --- DiscreteAngle.h | 11 +++++++++-- Range.cpp | 9 ++++++++- Range.h | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/DiscreteAngle.h b/DiscreteAngle.h index 0112584..4297c20 100644 --- a/DiscreteAngle.h +++ b/DiscreteAngle.h @@ -5,13 +5,20 @@ // A fixed angle between (-180..180] -template class AngleUsing : RangeUsing { +template class AngleUsing { public: AngleUsing(T sourceValue); float ToFloat(); inline T GetValue() { return this->value; } + + inline AngleUsing operator-(AngleUsing a) { + return this->value - a.value; + } + +protected: + T value; }; #endif -template inline float AngleUsing::ToFloat() { return 0.0f; } +// template inline float AngleUsing::ToFloat() { return 0.0f; } diff --git a/Range.cpp b/Range.cpp index 15bb7ca..d6b9e1b 100644 --- a/Range.cpp +++ b/Range.cpp @@ -38,4 +38,11 @@ bool Range16::operator<(Range16 a) { return (this->range < a.range); } bool Range16::operator>(Range16 a) { return (this->range > a.range); } bool Range16::operator<=(Range16 a) { return (this->range <= a.range); } bool Range16::operator>=(Range16 a) { return (this->range >= a.range); } -*/ \ No newline at end of file +*/ + +template <> RangeUsing::RangeUsing(float f) { + this->value = (unsigned char)((f + 1.0f) * 127.0F); +} +template <> RangeUsing::RangeUsing(float f) { + this->value = (unsigned short)((f + 1.0F) * 32767.0F); +} \ No newline at end of file diff --git a/Range.h b/Range.h index e521c71..bf632ae 100644 --- a/Range.h +++ b/Range.h @@ -30,6 +30,8 @@ protected: template class RangeUsing { public: + RangeUsing(float range); // range -1..1 + inline RangeUsing operator-(RangeUsing a) { this->value - a.value; } inline RangeUsing operator+(RangeUsing a) { this->value + a.value; } inline RangeUsing operator-() { this->value = -this.value; } From 159bdaec8ea8da678a456a827cdad737368f8d5f Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 13 Mar 2024 17:46:41 +0100 Subject: [PATCH 010/121] Added spherical.tovector (but is is buggy) --- Spherical.cpp | 8 ++++++++ Spherical.h | 1 + 2 files changed, 9 insertions(+) diff --git a/Spherical.cpp b/Spherical.cpp index 026d33b..4b230e4 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -1,6 +1,7 @@ #include "Spherical.h" #include "Angle.h" +#include "Quaternion.h" #include @@ -47,4 +48,11 @@ float Spherical::GetSwing() { Polar Spherical::ProjectOnHorizontalPlane() { return Polar(horizontalAngle, distance); +} + +Vector3 Spherical::ToVector3() { + Vector3 v = Quaternion::Euler( + Vector3(-this->verticalAngle, this->horizontalAngle, 0)) * + Vector3::forward * this->distance; + return v; } \ No newline at end of file diff --git a/Spherical.h b/Spherical.h index 7c98263..8231507 100644 --- a/Spherical.h +++ b/Spherical.h @@ -56,6 +56,7 @@ public: float GetSwing(); Polar ProjectOnHorizontalPlane(); + Vector3 ToVector3(); }; } // namespace Passer From dc601a1746ea150e306f3b9ef26c22a6ee702d99 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 14 Mar 2024 12:06:07 +0100 Subject: [PATCH 011/121] Removed Vector2.tofactor --- Vector2.cpp | 4 - Vector2.h | 404 +++++++++++++++++++++---------------------- test/Vector2_test.cc | 2 - 3 files changed, 201 insertions(+), 209 deletions(-) diff --git a/Vector2.cpp b/Vector2.cpp index b373299..c2a74c0 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -140,7 +140,3 @@ Vector2 Vector2::Lerp(Vector2 from, Vector2 to, float f) { Vector2 v = from + (to - from) * f; return v; } - -float Vector2::ToFactor(Vector2 a, Vector2 b) { - return (1 - Vector2::Dot(a, b)) / 2; -} diff --git a/Vector2.h b/Vector2.h index 1c4e329..c6877c4 100644 --- a/Vector2.h +++ b/Vector2.h @@ -6,22 +6,22 @@ #define VECTOR2_H extern "C" { - /// - /// 2-dimensional Vector representation - /// - /// This is a C-style implementation - /// This uses the right-handed coordinate system. - typedef struct Vec2 { - /// - /// The right axis of the vector - /// - float x; - /// - /// The upward/forward axis of the vector - /// - float y; +/// +/// 2-dimensional Vector representation +/// +/// This is a C-style implementation +/// This uses the right-handed coordinate system. +typedef struct Vec2 { + /// + /// The right axis of the vector + /// + float x; + /// + /// The upward/forward axis of the vector + /// + float y; - } Vec2; +} Vec2; } /// @@ -30,207 +30,205 @@ extern "C" { /// This uses the right-handed coordinate system. struct Vector2 : Vec2 { public: - /// - /// Create a new 2-dimensinal zero vector - /// - Vector2(); - /// - /// Create a new 2-dimensional vector - /// - /// x axis value - /// y axis value - Vector2(float x, float y); - /// - /// Create a vector from C-style Vec2 - /// - /// The C-style Vec - Vector2(Vec2 v); + /// + /// Create a new 2-dimensinal zero vector + /// + Vector2(); + /// + /// Create a new 2-dimensional vector + /// + /// x axis value + /// y axis value + Vector2(float x, float y); + /// + /// Create a vector from C-style Vec2 + /// + /// The C-style Vec + Vector2(Vec2 v); - ~Vector2(); + ~Vector2(); - /// - /// A vector with zero for all axis - /// - const static Vector2 zero; - /// - /// A vector with values (1, 1) - /// - const static Vector2 one; - /// - /// A vector with values (1, 0) - /// -/// - const static Vector2 right; - /// - /// A vector3 with values (-1, 0) - /// - const static Vector2 left; - /// - /// A vector with values (0, 1) - /// - const static Vector2 up; - /// - /// A vector with values (0, -1) - /// - const static Vector2 down; - /// - /// A vector with values (0, 1) - /// - const static Vector2 forward; - /// - /// A vector with values (0, -1) - /// - const static Vector2 back; + /// + /// A vector with zero for all axis + /// + const static Vector2 zero; + /// + /// A vector with values (1, 1) + /// + const static Vector2 one; + /// + /// A vector with values (1, 0) + /// + /// + const static Vector2 right; + /// + /// A vector3 with values (-1, 0) + /// + const static Vector2 left; + /// + /// A vector with values (0, 1) + /// + const static Vector2 up; + /// + /// A vector with values (0, -1) + /// + const static Vector2 down; + /// + /// A vector with values (0, 1) + /// + const static Vector2 forward; + /// + /// A vector with values (0, -1) + /// + const static Vector2 back; - /// - /// The length of a vector - /// - /// The vector for which you need the length - /// The length of the given vector - static float Magnitude(const Vector2& vector); - /// - /// The length of this vector - /// - /// The length of this vector - float magnitude() const; - /// - /// The squared length of a vector - /// - /// The vector for which you need the squared - /// length The squatred length The squared length - /// is computationally simpler than the real length. Think of Pythagoras A^2 + - /// B^2 = C^2. This leaves out the calculation of the squared root of C. - static float SqrMagnitude(const Vector2& vector); - /// - /// The squared length of this vector - /// - /// The squared length - /// The squared length is computationally simpler than the real length. - /// Think of Pythagoras A^2 + B^2 = C^2. - /// This leaves out the calculation of the squared root of C. - float sqrMagnitude() const; - /// - /// Connvert a vector to a length of 1 - /// - /// The vector to convert - /// The vector with length 1 - static Vector2 Normalize(Vector2 vector); - /// - /// Convert the vector to a length of a - /// - /// The vector with length 1 - Vector2 normalized() const; + /// + /// The length of a vector + /// + /// The vector for which you need the length + /// The length of the given vector + static float Magnitude(const Vector2 &vector); + /// + /// The length of this vector + /// + /// The length of this vector + float magnitude() const; + /// + /// The squared length of a vector + /// + /// The vector for which you need the squared + /// length The squatred length The squared length + /// is computationally simpler than the real length. Think of Pythagoras A^2 + + /// B^2 = C^2. This leaves out the calculation of the squared root of C. + static float SqrMagnitude(const Vector2 &vector); + /// + /// The squared length of this vector + /// + /// The squared length + /// The squared length is computationally simpler than the real length. + /// Think of Pythagoras A^2 + B^2 = C^2. + /// This leaves out the calculation of the squared root of C. + float sqrMagnitude() const; + /// + /// Connvert a vector to a length of 1 + /// + /// The vector to convert + /// The vector with length 1 + static Vector2 Normalize(Vector2 vector); + /// + /// Convert the vector to a length of a + /// + /// The vector with length 1 + Vector2 normalized() const; - /// - /// Negate the vector - /// - /// The negated vector - /// This will result in a vector pointing in the opposite direction - Vector2 operator-(); - /// - /// Subtract a vector from this vector - /// - /// The vector to subtract from this vector - /// The result of the subtraction - Vector2 operator-(const Vector2& vector) const; + /// + /// Negate the vector + /// + /// The negated vector + /// This will result in a vector pointing in the opposite direction + Vector2 operator-(); + /// + /// Subtract a vector from this vector + /// + /// The vector to subtract from this vector + /// The result of the subtraction + Vector2 operator-(const Vector2 &vector) const; - /// - /// Add another vector to this vector - /// - /// The vector to add - /// The result of adding the vector - Vector2 operator+(const Vector2& vector2) const; + /// + /// Add another vector to this vector + /// + /// The vector to add + /// The result of adding the vector + Vector2 operator+(const Vector2 &vector2) const; - /// - /// Scale a vector using another vector - /// - /// The vector to scale - /// A vector with scaling factors - /// The scaled vector - /// Each component of the vector v1 will be multiplied with the - /// component from the scaling vector v2. - static Vector2 Scale(const Vector2& vector1, const Vector2& vector2); - /// - /// Scale a vector uniformly up - /// - /// The scaling factor - /// The scaled vector - /// Each component of the vector will be multipled with the same factor. - Vector2 operator*(float factor) const; - /// - /// Scale a vector uniformy down - /// - /// The scaling factor - /// The scaled vector - /// Each componet of the vector will be divided by the same factor. - Vector2 operator/(const float& factor); + /// + /// Scale a vector using another vector + /// + /// The vector to scale + /// A vector with scaling factors + /// The scaled vector + /// Each component of the vector v1 will be multiplied with the + /// component from the scaling vector v2. + static Vector2 Scale(const Vector2 &vector1, const Vector2 &vector2); + /// + /// Scale a vector uniformly up + /// + /// The scaling factor + /// The scaled vector + /// Each component of the vector will be multipled with the same factor. + Vector2 operator*(float factor) const; + /// + /// Scale a vector uniformy down + /// + /// The scaling factor + /// The scaled vector + /// Each componet of the vector will be divided by the same factor. + Vector2 operator/(const float &factor); - /// - /// The dot product of two vectors - /// - /// The first vector - /// The second vector - /// The dot product of the two vectors - static float Dot(const Vector2& vector1, const Vector2& vector2); + /// + /// The dot product of two vectors + /// + /// The first vector + /// The second vector + /// The dot product of the two vectors + static float Dot(const Vector2 &vector1, const Vector2 &vector2); - /// - /// Check is this vector is equal to the given vector - /// - /// The vector to check against - /// True if it is identical to the given vector - /// Note this uses float comparison to check equality which - /// may have strange effects. Equality on float should be avoided. - bool operator==(const Vector2& vector); + /// + /// Check is this vector is equal to the given vector + /// + /// The vector to check against + /// True if it is identical to the given vector + /// Note this uses float comparison to check equality which + /// may have strange effects. Equality on float should be avoided. + bool operator==(const Vector2 &vector); - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vectors - /// The distance between the two vectors - static float Distance(const Vector2& vector1, const Vector2& vector2); + /// + /// The distance between two vectors + /// + /// The first vector + /// The second vectors + /// The distance between the two vectors + static float Distance(const Vector2 &vector1, const Vector2 &vector2); - /// - /// Calculate the angle between two vectors - /// - /// The first vector - /// The second vector - /// The angle - /// This reterns an unsigned angle which is the shortest distance - /// between the two vectors. Use Vector3::SignedAngle if a - /// signed angle is needed. - static float Angle(Vector2 vector1, Vector2 vector2); + /// + /// Calculate the angle between two vectors + /// + /// The first vector + /// The second vector + /// The angle + /// This reterns an unsigned angle which is the shortest distance + /// between the two vectors. Use Vector3::SignedAngle if a + /// signed angle is needed. + static float Angle(Vector2 vector1, Vector2 vector2); - /// - /// Calculate the angle between two vectors rotation around an axis. - /// - /// The starting vector - /// The ending vector - /// The axis to rotate around - /// The signed angle - static float SignedAngle(Vector2 from, Vector2 to); + /// + /// Calculate the angle between two vectors rotation around an axis. + /// + /// The starting vector + /// The ending vector + /// The axis to rotate around + /// The signed angle + static float SignedAngle(Vector2 from, Vector2 to); - /// - /// Rotate the vector - /// - /// The vector to rotate - /// Angle in radias to rotate - /// The rotated vector - static Vector2 Rotate(Vector2 v, float angle); + /// + /// Rotate the vector + /// + /// The vector to rotate + /// Angle in radias to rotate + /// The rotated vector + static Vector2 Rotate(Vector2 v, float angle); - /// - /// Lerp between two vectors - /// - /// The from vector - /// The to vector - /// The interpolation distance (0..1) - /// The lerped vector - /// The factor f is unclamped. Value 0 matches the *from* vector, Value 1 - /// matches the *to* vector Value -1 is *from* vector minus the difference - /// between *from* and *to* etc. - static Vector2 Lerp(Vector2 from, Vector2 to, float f); - - static float ToFactor(Vector2 a, Vector2 b); + /// + /// Lerp between two vectors + /// + /// The from vector + /// The to vector + /// The interpolation distance (0..1) + /// The lerped vector + /// The factor f is unclamped. Value 0 matches the *from* vector, Value 1 + /// matches the *to* vector Value -1 is *from* vector minus the difference + /// between *from* and *to* etc. + static Vector2 Lerp(Vector2 from, Vector2 to, float f); }; #endif \ No newline at end of file diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index 83c52ce..9303bb0 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -460,6 +460,4 @@ TEST(Vector2, Lerp) { EXPECT_FLOAT_EQ(Vector2::Distance(r, Vector2(-2.0, -1.0f)), 0); } -TEST(Vector2, DISABLED_ToFactor) {} - #endif \ No newline at end of file From 0cbef79a85a947f1a5681eaefb2fbece099d5be2 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 14 Mar 2024 12:14:19 +0100 Subject: [PATCH 012/121] Add first Spherical Unit test --- CMakeLists.txt | 1 + Spherical.cpp | 4 ++-- test/Spherical_test.cc | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/Spherical_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index d61999d..9fe0261 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ else() "test/Vector3_test.cc" "test/Quaternion_test.cc" "test/Matrix_test.cc" + "test/Spherical_test.cc" ) target_link_libraries( VectorAlgebraTest diff --git a/Spherical.cpp b/Spherical.cpp index 4b230e4..7253a09 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -32,9 +32,9 @@ Spherical::Spherical(float distance, Angle horizontalAngle, Angle verticalAngle) Spherical::Spherical(Vector3 v) { float signZ = (v.z >= 0) - (v.z < 0); - horizontalAngle = + verticalAngle = atan2(v.y, signZ * sqrt(v.z * v.z + v.x * v.x)) * Angle::Rad2Deg; - verticalAngle = -atan2(v.x, sqrt(v.z * v.z + v.y * v.y)) * Angle::Rad2Deg; + horizontalAngle = atan2(v.x, sqrt(v.z * v.z + v.y * v.y)) * Angle::Rad2Deg; distance = v.magnitude(); } diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc new file mode 100644 index 0000000..7ce4e5a --- /dev/null +++ b/test/Spherical_test.cc @@ -0,0 +1,32 @@ +#if GTEST +#include +#include +#include + +#include "Spherical.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Spherical, FromVector3) { + Vector3 v = Vector3(0, 0, 1); + Spherical s = Spherical::Spherical(v); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 0 0 1"; + + v = Vector3(0, 1, 0); + s = Spherical::Spherical(v); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.verticalAngle, 90.0F) << "s.vert 0 1 0"; + + v = Vector3(1, 0, 0); + s = Spherical::Spherical(v); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 1 0 0"; +} +#endif \ No newline at end of file From 395f82dc0c17c0439d561b821c68d36a5cf41bed Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 14 Mar 2024 12:21:32 +0100 Subject: [PATCH 013/121] Fix Spherical Unit test --- test/Spherical_test.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 7ce4e5a..6f9c527 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -9,21 +9,21 @@ TEST(Spherical, FromVector3) { Vector3 v = Vector3(0, 0, 1); - Spherical s = Spherical::Spherical(v); + Spherical s = Spherical(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 0 1"; EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); - s = Spherical::Spherical(v); + s = Spherical(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 1 0"; EXPECT_FLOAT_EQ(s.verticalAngle, 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); - s = Spherical::Spherical(v); + s = Spherical(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; EXPECT_FLOAT_EQ(s.horizontalAngle, 90.0F) << "s.hor 1 0 0"; From 7b85556f1ec02a2a1c78382a62e0221488a444fa Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 14 Mar 2024 12:37:22 +0100 Subject: [PATCH 014/121] Addedfirst Polar test --- CMakeLists.txt | 1 + Polar.cpp | 7 +++++++ Polar.h | 16 +++++++++++----- Vector2.cpp | 2 +- test/Polar_test.cc | 29 +++++++++++++++++++++++++++++ test/Vector2_test.cc | 14 ++++++++++++-- 6 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 test/Polar_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fe0261..372b7c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ else() "test/Vector3_test.cc" "test/Quaternion_test.cc" "test/Matrix_test.cc" + "test/Polar_test.cc" "test/Spherical_test.cc" ) target_link_libraries( diff --git a/Polar.cpp b/Polar.cpp index aa28e9a..2ad451c 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -19,6 +19,13 @@ Polar::Polar(float newAngle, float newDistance) { } } +Polar::Polar(Vector2 v) { + angle = Vector2::SignedAngle( + Vector2::forward, + v); // atan2(v.x, sqrt(v.z * v.z + v.y * v.y)) * Angle::Rad2Deg; + distance = v.magnitude(); +} + const Polar Polar::zero = Polar(0, 0); float Polar::Distance(const Polar &v1, const Polar &v2) { diff --git a/Polar.h b/Polar.h index cbb161f..48d9f17 100644 --- a/Polar.h +++ b/Polar.h @@ -5,13 +5,15 @@ #ifndef POLAR_H #define POLAR_H +struct Vector2; + /// /// A polar vector /// /// This will use the polar coordinate system consisting of a angle from a /// reference direction and a distance. struct Polar { - public: +public: /// /// The angle in degrees, clockwise rotation /// @@ -34,6 +36,8 @@ struct Polar { /// The distance in meters Polar(float angle, float distance); + Polar(Vector2 v); + /// /// A polar vector with zero degrees and distance /// @@ -51,14 +55,14 @@ struct Polar { /// /// The vector to subtract from this vector /// The result of the subtraction - Polar operator-(const Polar& v) const; + Polar operator-(const Polar &v) const; /// /// Add another polar vector to this polar vector /// /// The vector to add /// The result of adding the vector - Polar operator+(const Polar& v) const; + Polar operator+(const Polar &v) const; /// /// Scale the vector uniformly up @@ -76,7 +80,7 @@ struct Polar { /// The scaled vector /// This operation will scale the distance of the vector. The angle will be /// unaffected. - Polar operator/(const float& factor); + Polar operator/(const float &factor); /// /// The distance between two vectors @@ -84,7 +88,7 @@ struct Polar { /// The first vector /// The second vector /// The distance between the two vectors - static float Distance(const Polar& v1, const Polar& v2); + static float Distance(const Polar &v1, const Polar &v2); /// /// Rotate the vector @@ -95,4 +99,6 @@ struct Polar { static Polar Rotate(Polar v, float angle); }; +#include "Vector2.h" + #endif \ No newline at end of file diff --git a/Vector2.cpp b/Vector2.cpp index c2a74c0..dbf6562 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -116,7 +116,7 @@ float Vector2::SignedAngle(Vector2 from, Vector2 to) { float angleFrom = atan2(from.y, from.x); float angleTo = atan2(to.y, to.x); - return (angleTo - angleFrom) * Angle::Rad2Deg; + return -(angleTo - angleFrom) * Angle::Rad2Deg; } Vector2 Vector2::Rotate(Vector2 v, float angle) { diff --git a/test/Polar_test.cc b/test/Polar_test.cc new file mode 100644 index 0000000..ebadeee --- /dev/null +++ b/test/Polar_test.cc @@ -0,0 +1,29 @@ +#if GTEST +#include +#include +#include + +#include "Polar.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Polar, FromVector2) { + Vector2 v = Vector2(0, 1); + Polar p = Polar::Polar(v); + + EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1"; + EXPECT_FLOAT_EQ(p.angle, 0.0F) << "s.angle 0 0 1"; + + v = Vector2(1, 0); + p = Polar::Polar(v); + + EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0"; + EXPECT_FLOAT_EQ(p.angle, 90.0F) << "s.angle 1 0"; + + v = Vector2(-1, 1); + p = Polar::Polar(v); + + EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1"; + EXPECT_NEAR(p.angle, -45.0F, 1.0e-05) << "s.angle -1 1"; +} +#endif \ No newline at end of file diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index 9303bb0..88b8c97 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -399,11 +399,11 @@ TEST(Vector2, SignedAngle) { bool r = false; f = Vector2::SignedAngle(v1, v2); - EXPECT_FLOAT_EQ(f, 12.09476F) << "SignedAngle(4 5, 1 2)"; + EXPECT_FLOAT_EQ(f, -12.09476F) << "SignedAngle(4 5, 1 2)"; v2 = Vector2(-1, -2); f = Vector2::SignedAngle(v1, v2); - EXPECT_FLOAT_EQ(f, -167.9052F) << "SignedAngle(4 5, -1 -2)"; + EXPECT_FLOAT_EQ(f, 167.9052F) << "SignedAngle(4 5, -1 -2)"; v2 = Vector2(0, 0); f = Vector2::SignedAngle(v1, v2); @@ -420,6 +420,16 @@ TEST(Vector2, SignedAngle) { r = isnan(f); EXPECT_TRUE(r) << "SignedAngle(4 5, -INFINITY -INFINITY)"; } + + v1 = Vector2(0, 1); + v2 = Vector2(1, 0); + f = Vector2::SignedAngle(v1, v2); + EXPECT_FLOAT_EQ(f, 90.0F) << "SignedAngle(0 1, 1 0)"; + + v1 = Vector2(0, 1); + v2 = Vector2(0, -1); + f = Vector2::SignedAngle(v1, v2); + EXPECT_FLOAT_EQ(f, 180.0F) << "SignedAngle(0 1, 1 0)"; } TEST(Vector2, Rotate) { From 8e3b9e2b2d8032a742835d951038b30fec627a9d Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 14 Mar 2024 12:39:34 +0100 Subject: [PATCH 015/121] Fix Polar test --- test/Polar_test.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Polar_test.cc b/test/Polar_test.cc index ebadeee..be83dd4 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -9,19 +9,19 @@ TEST(Polar, FromVector2) { Vector2 v = Vector2(0, 1); - Polar p = Polar::Polar(v); + Polar p = Polar(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1"; EXPECT_FLOAT_EQ(p.angle, 0.0F) << "s.angle 0 0 1"; v = Vector2(1, 0); - p = Polar::Polar(v); + p = Polar(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0"; EXPECT_FLOAT_EQ(p.angle, 90.0F) << "s.angle 1 0"; v = Vector2(-1, 1); - p = Polar::Polar(v); + p = Polar(v); EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1"; EXPECT_NEAR(p.angle, -45.0F, 1.0e-05) << "s.angle -1 1"; From 5141766de58b4d988ff1e4eb6e83f32257034ee4 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 14 Mar 2024 15:27:34 +0100 Subject: [PATCH 016/121] Add spherical.toVector3 test (and fixes) --- Spherical.cpp | 11 ++++++++--- test/Spherical_test.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index 7253a09..6de28a7 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -51,8 +51,13 @@ Polar Spherical::ProjectOnHorizontalPlane() { } Vector3 Spherical::ToVector3() { - Vector3 v = Quaternion::Euler( - Vector3(-this->verticalAngle, this->horizontalAngle, 0)) * - Vector3::forward * this->distance; + // Vector3 v = Quaternion::AngleAxis(this->horizontalAngle, Vector3::up) * + // Quaternion::AngleAxis(this->verticalAngle, Vector3::left) * + // Vector3::forward * this->distance; + float verticalRad = verticalAngle * Angle::Deg2Rad; + float horizontalRad = horizontalAngle * Angle::Deg2Rad; + Vector3 v = Vector3(this->distance * cosf(verticalRad) * sinf(horizontalRad), + this->distance * sinf(verticalRad), + this->distance * cosf(verticalRad) * cosf(horizontalRad)); return v; } \ No newline at end of file diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 6f9c527..bea62e0 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -29,4 +29,30 @@ TEST(Spherical, FromVector3) { EXPECT_FLOAT_EQ(s.horizontalAngle, 90.0F) << "s.hor 1 0 0"; EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 1 0 0"; } + +TEST(Spherical, ToVector3) { + Vector3 v = Vector3(0, 0, 1); + Spherical s = Spherical(v); + Vector3 r = s.ToVector3(); + + EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 0 1"; + EXPECT_FLOAT_EQ(r.y, 0.0F) << "toVector3.y 0 0 1"; + EXPECT_FLOAT_EQ(r.z, 1.0F) << "toVector3.z 0 0 1"; + + v = Vector3(0, 1, 0); + s = Spherical(v); + r = s.ToVector3(); + + EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 1 0"; + EXPECT_FLOAT_EQ(r.y, 1.0F) << "toVector3.y 0 1 0"; + EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; + + v = Vector3(1, 0, 0); + s = Spherical(v); + r = s.ToVector3(); + + EXPECT_FLOAT_EQ(r.x, 1.0F) << "toVector3.x 1 0 0"; + EXPECT_FLOAT_EQ(r.y, 0.0F) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; +} #endif \ No newline at end of file From 87d2c11ab6243ebdf82d874676261d45ad2c3eea Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 09:27:23 +0100 Subject: [PATCH 017/121] Set strict warnings --- CMakeLists.txt | 7 +++++++ DiscreteAngle.cpp | 8 ++++++-- DiscreteAngle.h | 21 ++++++++++++++++----- Matrix.h | 4 ++-- test/Matrix_test.cc | 3 ++- test/Vector2_test.cc | 12 ------------ test/Vector3_test.cc | 12 ------------ 7 files changed, 33 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 372b7c0..ef430ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,13 @@ else() VectorAlgebra ) + if(MSVC) + target_compile_options(VectorAlgebraTest PRIVATE /W4 /WX) + else() + target_compile_options(VectorAlgebraTest PRIVATE -Wall -Wextra -Wpedantic -Werror) + endif() + + include(GoogleTest) gtest_discover_tests(VectorAlgebraTest) endif() diff --git a/DiscreteAngle.cpp b/DiscreteAngle.cpp index 0a0e4cd..6cff5f8 100644 --- a/DiscreteAngle.cpp +++ b/DiscreteAngle.cpp @@ -7,6 +7,8 @@ #include "Angle.h" #include +// 1-byte angle + template <> AngleUsing::AngleUsing(unsigned char angle) { if (!isfinite(angle)) { value = 0; @@ -21,11 +23,13 @@ template <> AngleUsing::AngleUsing(unsigned char angle) { this->value = (unsigned char)((angle + 180.0F) / 360.0F * 255.0F); } -template <> float AngleUsing::ToFloat() { +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; @@ -40,7 +44,7 @@ template <> AngleUsing::AngleUsing(unsigned short angle) { this->value = (unsigned short)((angle + 180.0F) / 360.0F * 65535.0F); } -template <> float AngleUsing::ToFloat() { +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 index 4297c20..8f7454a 100644 --- a/DiscreteAngle.h +++ b/DiscreteAngle.h @@ -8,17 +8,28 @@ template class AngleUsing { public: AngleUsing(T sourceValue); - float ToFloat(); - inline T GetValue() { return this->value; } + float ToFloat() const; + inline T GetValue() const { return this->value; } - inline AngleUsing operator-(AngleUsing a) { + 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 - -// template inline float AngleUsing::ToFloat() { return 0.0f; } diff --git a/Matrix.h b/Matrix.h index 5ef0588..7eb80a9 100644 --- a/Matrix.h +++ b/Matrix.h @@ -33,7 +33,7 @@ public: // Return a null matrix; // We dont set data to nullptr because it is allocated memory // Instead we write all zeros - for (int dataIx = 0; dataIx < resultSize; dataIx++) + for (unsigned int dataIx = 0; dataIx < resultSize; dataIx++) r->data[dataIx] = 0.0f; r->rows = 0; r->cols = 0; @@ -43,7 +43,7 @@ public: r->cols = this->rows; r->rows = this->cols; - for (int rDataIx = 0; rDataIx < matrixSize; rDataIx++) { + for (unsigned int rDataIx = 0; rDataIx < matrixSize; rDataIx++) { unsigned int rowIx = rDataIx / this->rows; unsigned int colIx = rDataIx % this->rows; unsigned int mDataIx = this->cols * colIx + rowIx; diff --git a/test/Matrix_test.cc b/test/Matrix_test.cc index dd358f9..a1267cf 100644 --- a/test/Matrix_test.cc +++ b/test/Matrix_test.cc @@ -18,7 +18,8 @@ TEST(MatrixSingle, Init) { MatrixOf m2 = MatrixOf(2, 2, data2); // negative - MatrixOf m_1 = MatrixOf(-1, -1); + // MatrixOf m_1 = MatrixOf(-1, -1); + // parameters are unsigned } TEST(MatrixSingle, Transpose) { diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index 88b8c97..ba16470 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -99,8 +99,6 @@ TEST(Vector2, Normalize) { } TEST(Vector2, Negate) { - bool r = false; - Vector2 v1 = Vector2(4, 5); Vector2 v = Vector2::zero; @@ -129,8 +127,6 @@ TEST(Vector2, Negate) { } TEST(Vector2, Subtract) { - bool r = false; - Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 v = Vector2::zero; @@ -164,11 +160,9 @@ TEST(Vector2, Subtract) { } TEST(Vector2, Addition) { - Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 v = Vector2::zero; - bool r = false; v = v1 + v2; EXPECT_TRUE(v == Vector2(5, 7)) << "4 5 + 1 2"; @@ -195,8 +189,6 @@ TEST(Vector2, Addition) { } TEST(Vector2, Scale) { - bool r = false; - Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 v = Vector2::zero; @@ -226,8 +218,6 @@ TEST(Vector2, Scale) { } TEST(Vector2, Multiply) { - bool r = false; - Vector2 v1 = Vector2(4, 5); float f = 3; Vector2 v = Vector2::zero; @@ -257,8 +247,6 @@ TEST(Vector2, Multiply) { } TEST(Vector2, Divide) { - bool r = false; - Vector2 v1 = Vector2(4, 5); float f = 2; Vector2 v = Vector2::zero; diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index e8f61f8..2148937 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -103,8 +103,6 @@ TEST(Vector3, Normalize) { } TEST(Vector3, Negate) { - bool r = false; - Vector3 v1 = Vector3(4, 5, 6); Vector3 v = Vector3::zero; @@ -133,8 +131,6 @@ TEST(Vector3, Negate) { } TEST(Vector3, Subtract) { - bool r = false; - Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; @@ -168,11 +164,9 @@ TEST(Vector3, Subtract) { } TEST(Vector3, Addition) { - Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; - bool r = false; v = v1 + v2; EXPECT_TRUE(v == Vector3(5, 7, 9)) << "4 5 6 + 1 2 3"; @@ -199,8 +193,6 @@ TEST(Vector3, Addition) { } TEST(Vector3, Scale) { - bool r = false; - Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; @@ -230,8 +222,6 @@ TEST(Vector3, Scale) { } TEST(Vector3, Multiply) { - bool r = false; - Vector3 v1 = Vector3(4, 5, 6); float f = 3; Vector3 v = Vector3::zero; @@ -261,8 +251,6 @@ TEST(Vector3, Multiply) { } TEST(Vector3, Divide) { - bool r = false; - Vector3 v1 = Vector3(4, 5, 6); float f = 2; Vector3 v = Vector3::zero; From e62bacc6b4c5ea129f3caa3058d1c1176b69486a Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 10:46:30 +0100 Subject: [PATCH 018/121] First Discrete Angle functions --- Angle16.h | 21 ++++++++++ Angle8.h | 22 ++++++++++ AngleUsing.cpp | 83 ++++++++++++++++++++++++++++++++++++++ AngleUsing.h | 42 +++++++++++++++++++ CMakeLists.txt | 1 + DiscreteAngle.cpp | 50 ----------------------- DiscreteAngle.h | 35 ---------------- test/DiscreteAngle_test.cc | 64 +++++++++++++++++++++++++++++ 8 files changed, 233 insertions(+), 85 deletions(-) create mode 100644 Angle16.h create mode 100644 Angle8.h create mode 100644 AngleUsing.cpp create mode 100644 AngleUsing.h delete mode 100644 DiscreteAngle.cpp delete mode 100644 DiscreteAngle.h create mode 100644 test/DiscreteAngle_test.cc 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 From 3e5ede06d6d769efb6ebc5417a6746447181441b Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 10:47:08 +0100 Subject: [PATCH 019/121] Removed old file --- AngleUsing.cpp | 83 -------------------------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 AngleUsing.cpp diff --git a/AngleUsing.cpp b/AngleUsing.cpp deleted file mode 100644 index 37d4bf1..0000000 --- a/AngleUsing.cpp +++ /dev/null @@ -1,83 +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; -// } - -// 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 From 430344adc130df6a6e5ebc8a4bf216ccae9f92b5 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 11:23:49 +0100 Subject: [PATCH 020/121] Fix specialization error --- Angle16.h | 4 ++-- Angle8.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Angle16.h b/Angle16.h index 410c5f7..d550c54 100644 --- a/Angle16.h +++ b/Angle16.h @@ -5,7 +5,7 @@ typedef AngleUsing Angle16; -Angle16::AngleUsing(float angle) { +AngleUsing::AngleUsing(float angle) { if (!isfinite(angle)) { value = 0; return; @@ -15,7 +15,7 @@ Angle16::AngleUsing(float angle) { this->value = (signed short)((angle / 360.0F) * 65536.0F); } -float Angle16::ToFloat() const { +float AngleUsing::ToFloat() const { float f = ((this->value * 180) / 32768.0F); return f; } diff --git a/Angle8.h b/Angle8.h index 2db4d18..4a31500 100644 --- a/Angle8.h +++ b/Angle8.h @@ -5,7 +5,7 @@ typedef AngleUsing Angle8; -Angle8::AngleUsing(float angle) { +AngleUsing::AngleUsing(float angle) { if (!isfinite(angle)) { value = 0; return; @@ -16,7 +16,7 @@ Angle8::AngleUsing(float angle) { this->value = (signed char)(f * 256.0F); } -float Angle8::ToFloat() const { +float AngleUsing::ToFloat() const { float f = (this->value * 180) / 128.0F; return f; } From e62fa9625317dfe3bbab0e75dd7727027f66afe5 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 11:26:48 +0100 Subject: [PATCH 021/121] Fix specialization again --- Angle16.h | 4 ++-- Angle8.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Angle16.h b/Angle16.h index d550c54..fd62d1d 100644 --- a/Angle16.h +++ b/Angle16.h @@ -5,7 +5,7 @@ typedef AngleUsing Angle16; -AngleUsing::AngleUsing(float angle) { +template <> Angle16::AngleUsing(float angle) { if (!isfinite(angle)) { value = 0; return; @@ -15,7 +15,7 @@ AngleUsing::AngleUsing(float angle) { this->value = (signed short)((angle / 360.0F) * 65536.0F); } -float AngleUsing::ToFloat() const { +template <> float Angle16::ToFloat() const { float f = ((this->value * 180) / 32768.0F); return f; } diff --git a/Angle8.h b/Angle8.h index 4a31500..22c8745 100644 --- a/Angle8.h +++ b/Angle8.h @@ -5,7 +5,7 @@ typedef AngleUsing Angle8; -AngleUsing::AngleUsing(float angle) { +template <> Angle8::AngleUsing(float angle) { if (!isfinite(angle)) { value = 0; return; @@ -16,7 +16,7 @@ AngleUsing::AngleUsing(float angle) { this->value = (signed char)(f * 256.0F); } -float AngleUsing::ToFloat() const { +template <> float Angle8::ToFloat() const { float f = (this->value * 180) / 128.0F; return f; } From 89b5da8e09afc5be5a1887b5572b41f678655820 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 11:28:46 +0100 Subject: [PATCH 022/121] Fix ambiguity --- AngleUsing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AngleUsing.h b/AngleUsing.h index d6eb4d0..156fd6e 100644 --- a/AngleUsing.h +++ b/AngleUsing.h @@ -14,7 +14,7 @@ public: inline T GetValue() const { return this->value; } AngleUsing operator+(const AngleUsing a) { - AngleUsing r = AngleUsing(this->value + a.value); + AngleUsing r = AngleUsing((float)this->value + a.value); return r; } From ec0cc4784685a75c8b20023942b878f5fa0cafdf Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 15:36:52 +0100 Subject: [PATCH 023/121] Fix spherical to vector --- Spherical.cpp | 21 ++++++++-------- test/Spherical_test.cc | 54 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index 6de28a7..29d9957 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -31,11 +31,9 @@ Spherical::Spherical(float distance, Angle horizontalAngle, Angle verticalAngle) verticalAngle(verticalAngle) {} Spherical::Spherical(Vector3 v) { - float signZ = (v.z >= 0) - (v.z < 0); - verticalAngle = - atan2(v.y, signZ * sqrt(v.z * v.z + v.x * v.x)) * Angle::Rad2Deg; - horizontalAngle = atan2(v.x, sqrt(v.z * v.z + v.y * v.y)) * Angle::Rad2Deg; distance = v.magnitude(); + verticalAngle = 90 - acosf(v.y / distance) * Angle::Rad2Deg; + horizontalAngle = atanf(v.x / v.z) * Angle::Rad2Deg; } const Spherical Spherical::zero = Spherical(0.0F, (Angle)0.0F, (Angle)0.0F); @@ -51,13 +49,14 @@ Polar Spherical::ProjectOnHorizontalPlane() { } Vector3 Spherical::ToVector3() { - // Vector3 v = Quaternion::AngleAxis(this->horizontalAngle, Vector3::up) * - // Quaternion::AngleAxis(this->verticalAngle, Vector3::left) * - // Vector3::forward * this->distance; - float verticalRad = verticalAngle * Angle::Deg2Rad; + float verticalRad = (90 - verticalAngle) * Angle::Deg2Rad; float horizontalRad = horizontalAngle * Angle::Deg2Rad; - Vector3 v = Vector3(this->distance * cosf(verticalRad) * sinf(horizontalRad), - this->distance * sinf(verticalRad), - this->distance * cosf(verticalRad) * cosf(horizontalRad)); + float cosVertical = cosf(verticalRad); + float sinVertical = sinf(verticalRad); + float cosHorizontal = cosf(horizontalRad); + float sinHorizontal = sinf(horizontalRad); + Vector3 v = Vector3(this->distance * sinVertical * sinHorizontal, + this->distance * cosVertical, + this->distance * sinVertical * cosHorizontal); return v; } \ No newline at end of file diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index bea62e0..ac1f24a 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -55,4 +55,58 @@ TEST(Spherical, ToVector3) { EXPECT_FLOAT_EQ(r.y, 0.0F) << "toVector3.y 1 0 0"; EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; } + +TEST(Spherical, Incident1) { + Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); + Spherical s = Spherical(v); + Vector3 r = s.ToVector3(); + + EXPECT_NEAR(r.x, v.x, 1.0e-06) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.y, v.y, 1.0e-06) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.z, v.z, 1.0e-06) << "toVector3.z 1 0 0"; +} + +TEST(Spherical, Incident2) { + Vector3 v = Vector3(1.0f, 0.0f, 1.0f); + Spherical s = Spherical(v); + Vector3 r = s.ToVector3(); + + EXPECT_NEAR(s.distance, 1.4142135623F, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-05); + EXPECT_NEAR(s.verticalAngle, 0.0F, 1.0e-05); + + EXPECT_NEAR(r.x, v.x, 1.0e-06); + EXPECT_NEAR(r.y, v.y, 1.0e-06); + EXPECT_NEAR(r.z, v.z, 1.0e-06); + + v = Vector3(0.0f, 1.0f, 1.0f); + s = Spherical(v); + r = s.ToVector3(); + + EXPECT_NEAR(s.distance, 1.4142135623F, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle, 0.0F, 1.0e-05); + EXPECT_NEAR(s.verticalAngle, 45.0F, 1.0e-05); + + EXPECT_NEAR(r.x, v.x, 1.0e-06); + EXPECT_NEAR(r.y, v.y, 1.0e-06); + EXPECT_NEAR(r.z, v.z, 1.0e-06); + + v = Vector3(1.0f, 1.0f, 1.0f); + s = Spherical(v); + r = s.ToVector3(); + + EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-06); + EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); + // EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-06); + + EXPECT_NEAR(r.x, v.x, 1.0e-06); + EXPECT_NEAR(r.y, v.y, 1.0e-06); + EXPECT_NEAR(r.z, v.z, 1.0e-06); + + // s = Spherical(10, 45, 45); + // r = s.ToVector3(); + // EXPECT_NEAR(r.x, 5, 1.0e-06); + // EXPECT_NEAR(r.y, 7.07, 1.0e-06); + // EXPECT_NEAR(r.z, 5, 1.0e-06); +} #endif \ No newline at end of file From ae55a24dc09d1603179b388d90297be3a4eb457c Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 15 Mar 2024 17:20:21 +0100 Subject: [PATCH 024/121] Further vector3 conversion fixes --- Spherical.cpp | 16 +++++++--------- test/Spherical_test.cc | 39 +++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index 29d9957..2449a6c 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -13,13 +13,6 @@ Spherical::Spherical() { this->distance = 0; } -// Spherical::Spherical(float polarAngle, float elevationAngle, float distance) -// { -// this->horizontalAngle = polarAngle; -// this->verticalAngle = elevationAngle; -// this->distance = distance; -// } - Spherical::Spherical(Polar polar) { this->horizontalAngle = polar.angle; this->verticalAngle = 0.0F; @@ -32,8 +25,13 @@ Spherical::Spherical(float distance, Angle horizontalAngle, Angle verticalAngle) Spherical::Spherical(Vector3 v) { distance = v.magnitude(); - verticalAngle = 90 - acosf(v.y / distance) * Angle::Rad2Deg; - horizontalAngle = atanf(v.x / v.z) * Angle::Rad2Deg; + if (distance == 0.0f) { + verticalAngle = 0; + horizontalAngle = 0; + } else { + verticalAngle = (90 - acosf(v.y / distance) * Angle::Rad2Deg); + horizontalAngle = atan2f(v.x, v.z) * Angle::Rad2Deg; + } } const Spherical Spherical::zero = Spherical(0.0F, (Angle)0.0F, (Angle)0.0F); diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index ac1f24a..973bac0 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -36,7 +36,7 @@ TEST(Spherical, ToVector3) { Vector3 r = s.ToVector3(); EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 0 1"; - EXPECT_FLOAT_EQ(r.y, 0.0F) << "toVector3.y 0 0 1"; + EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; EXPECT_FLOAT_EQ(r.z, 1.0F) << "toVector3.z 0 0 1"; v = Vector3(0, 1, 0); @@ -52,41 +52,48 @@ TEST(Spherical, ToVector3) { r = s.ToVector3(); EXPECT_FLOAT_EQ(r.x, 1.0F) << "toVector3.x 1 0 0"; - EXPECT_FLOAT_EQ(r.y, 0.0F) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; } TEST(Spherical, Incident1) { Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); Spherical s = Spherical(v); - Vector3 r = s.ToVector3(); - EXPECT_NEAR(r.x, v.x, 1.0e-06) << "toVector3.x 1 0 0"; - EXPECT_NEAR(r.y, v.y, 1.0e-06) << "toVector3.y 1 0 0"; - EXPECT_NEAR(r.z, v.z, 1.0e-06) << "toVector3.z 1 0 0"; + Spherical sr = Spherical(2.49F, 98.18f, 24.4F); + EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); + EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-02); + EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-02); + + Vector3 r = sr.ToVector3(); + EXPECT_NEAR(r.x, v.x, 1.0e-02) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.y, v.y, 1.0e-02) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.z, v.z, 1.0e-02) << "toVector3.z 1 0 0"; } TEST(Spherical, Incident2) { Vector3 v = Vector3(1.0f, 0.0f, 1.0f); Spherical s = Spherical(v); - Vector3 r = s.ToVector3(); - EXPECT_NEAR(s.distance, 1.4142135623F, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-05); - EXPECT_NEAR(s.verticalAngle, 0.0F, 1.0e-05); + Spherical sr = Spherical(1.4142135623F, 45.0f, 0.0F); + EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); + EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + Vector3 r = sr.ToVector3(); EXPECT_NEAR(r.x, v.x, 1.0e-06); EXPECT_NEAR(r.y, v.y, 1.0e-06); EXPECT_NEAR(r.z, v.z, 1.0e-06); v = Vector3(0.0f, 1.0f, 1.0f); s = Spherical(v); - r = s.ToVector3(); - EXPECT_NEAR(s.distance, 1.4142135623F, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle, 0.0F, 1.0e-05); - EXPECT_NEAR(s.verticalAngle, 45.0F, 1.0e-05); + sr = Spherical(1.4142135623F, 0.0f, 45.0F); + EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); + EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + r = sr.ToVector3(); EXPECT_NEAR(r.x, v.x, 1.0e-06); EXPECT_NEAR(r.y, v.y, 1.0e-06); EXPECT_NEAR(r.z, v.z, 1.0e-06); @@ -95,9 +102,9 @@ TEST(Spherical, Incident2) { s = Spherical(v); r = s.ToVector3(); - EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-06); + EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); - // EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-06); + EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-02); EXPECT_NEAR(r.x, v.x, 1.0e-06); EXPECT_NEAR(r.y, v.y, 1.0e-06); From 264bcbc0baecce430c436bfe453a729c4b4bfb93 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 5 Apr 2024 11:33:35 +0200 Subject: [PATCH 025/121] Added 32 bit angle --- Angle32.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Angle32.h diff --git a/Angle32.h b/Angle32.h new file mode 100644 index 0000000..4820af6 --- /dev/null +++ b/Angle32.h @@ -0,0 +1,21 @@ +#include "AngleUsing.h" + +#include "Angle.h" +#include + +typedef AngleUsing Angle32; + +template <> Angle32::AngleUsing(float angle) { + if (!isfinite(angle)) { + value = 0; + return; + } + + // map float [-180..180) to integer [-2147483648..2147483647] + this->value = (signed short)((angle / 360.0F) * 4294967295.0F); +} + +template <> float Angle32::ToFloat() const { + float f = ((this->value * 180) / 2147483648.0F); + return f; +} From 66ff721dfe5da8209d3650a530364235630aeb40 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 5 Apr 2024 11:59:36 +0200 Subject: [PATCH 026/121] Fixed wrong conversion to short --- Angle32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Angle32.h b/Angle32.h index 4820af6..7d8ce10 100644 --- a/Angle32.h +++ b/Angle32.h @@ -12,7 +12,7 @@ template <> Angle32::AngleUsing(float angle) { } // map float [-180..180) to integer [-2147483648..2147483647] - this->value = (signed short)((angle / 360.0F) * 4294967295.0F); + this->value = (signed long)((angle / 360.0F) * 4294967295.0F); } template <> float Angle32::ToFloat() const { From c274c3eac9ee06e898add3a46faa254dc68657ba Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 19 Apr 2024 12:16:20 +0200 Subject: [PATCH 027/121] Add conversion from Spherical --- Polar.cpp | 6 ++++++ Polar.h | 1 + 2 files changed, 7 insertions(+) diff --git a/Polar.cpp b/Polar.cpp index 2ad451c..421962e 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -2,6 +2,7 @@ #include "Angle.h" #include "Polar.h" +#include "Spherical.h" Polar::Polar() { angle = 0.0F; @@ -26,6 +27,11 @@ Polar::Polar(Vector2 v) { distance = v.magnitude(); } +Polar::Polar(Spherical s) { + angle = s.horizontalAngle; + distance = s.distance * cosf(s.verticalAngle * Angle::Deg2Rad); +} + const Polar Polar::zero = Polar(0, 0); float Polar::Distance(const Polar &v1, const Polar &v2) { diff --git a/Polar.h b/Polar.h index 48d9f17..fa6c287 100644 --- a/Polar.h +++ b/Polar.h @@ -37,6 +37,7 @@ public: Polar(float angle, float distance); Polar(Vector2 v); + Polar(Spherical s); /// /// A polar vector with zero degrees and distance From fe12c99159706688925b57ed24b61f651825e117 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 19 Apr 2024 14:43:00 +0200 Subject: [PATCH 028/121] Fix Spherical reference --- Polar.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Polar.h b/Polar.h index fa6c287..78d2b69 100644 --- a/Polar.h +++ b/Polar.h @@ -7,6 +7,10 @@ struct Vector2; +namespace Passer { + +struct Spherical; + /// /// A polar vector /// @@ -37,6 +41,7 @@ public: Polar(float angle, float distance); Polar(Vector2 v); + Polar(Spherical s); /// @@ -99,7 +104,8 @@ public: /// The rotated vector static Polar Rotate(Polar v, float angle); }; - +} // namespace Passer +#include "Spherical.h" #include "Vector2.h" #endif \ No newline at end of file From 4b07328790ffd565f9f3303b625dbde68abaecc7 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 25 Apr 2024 15:22:05 +0200 Subject: [PATCH 029/121] Add conversion from Vector3 --- Vector2.cpp | 6 ++++++ Vector2.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/Vector2.cpp b/Vector2.cpp index dbf6562..2d1ff19 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -5,6 +5,7 @@ #include "Vector2.h" #include "Angle.h" #include "FloatSingle.h" +#include "Vector3.h" #if defined(AVR) #include @@ -27,6 +28,11 @@ Vector2::Vector2(Vec2 v) { y = v.y; } +Vector2::Vector2(Vector3 v) { + x = v.x; + y = v.z; +} + Vector2::~Vector2() {} const Vector2 Vector2::zero = Vector2(0, 0); diff --git a/Vector2.h b/Vector2.h index c6877c4..4d88ed3 100644 --- a/Vector2.h +++ b/Vector2.h @@ -24,6 +24,8 @@ typedef struct Vec2 { } Vec2; } +class Vector3; + /// /// A 2-dimensional vector /// @@ -46,6 +48,8 @@ public: /// The C-style Vec Vector2(Vec2 v); + Vector2(Vector3 v); + ~Vector2(); /// From 4385befa113d47bf700465625442ab4aa71fe9b8 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 26 Apr 2024 12:11:48 +0200 Subject: [PATCH 030/121] Add angle-axis --- AngleAxis.cpp | 15 +++++++++++++++ AngleAxis.h | 20 ++++++++++++++++++++ Axis.cpp | 39 +++++++++++++++++++++++++++++++++++++++ Axis.h | 31 +++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 AngleAxis.cpp create mode 100644 AngleAxis.h create mode 100644 Axis.cpp create mode 100644 Axis.h diff --git a/AngleAxis.cpp b/AngleAxis.cpp new file mode 100644 index 0000000..9cc1f1e --- /dev/null +++ b/AngleAxis.cpp @@ -0,0 +1,15 @@ +// 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 "AngleAxis.h" + +AngleAxis::AngleAxis() { + angle = Angle(); + axis = Axis(); +} + +AngleAxis::AngleAxis(Angle angle, Axis axis) { + this->angle = angle; + this->axis = axis; +} \ No newline at end of file diff --git a/AngleAxis.h b/AngleAxis.h new file mode 100644 index 0000000..68eda55 --- /dev/null +++ b/AngleAxis.h @@ -0,0 +1,20 @@ +// 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/. + +#ifndef ANGLEAXIS_H +#define ANGLEAXIS_H + +#include "Angle.h" +#include "Axis.h" + +class AngleAxis { +public: + Angle angle; + Axis axis; + + AngleAxis(); + AngleAxis(Angle angle, Axis axis); +}; + +#endif \ No newline at end of file diff --git a/Axis.cpp b/Axis.cpp new file mode 100644 index 0000000..0b21ac0 --- /dev/null +++ b/Axis.cpp @@ -0,0 +1,39 @@ +// 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 "Axis.h" + +#include "Quaternion.h" +#include "Vector3.h" + +#include + +Axis::Axis() { + horizontalAngle = 0; + verticalAngle = 0; +} + +Axis::Axis(Angle horizontal, Angle vertical) { + this->horizontalAngle = horizontal; + this->verticalAngle = vertical; +}; + +Axis::Axis(Vector3 v) { + this->horizontalAngle = atan2f(v.x, v.z) * Angle::Rad2Deg; + this->verticalAngle = 90 - acosf(v.y) * Angle::Rad2Deg; +} + +const Axis Axis::forward = Axis(0, 0); +const Axis Axis::back = Axis(180, 0); +const Axis Axis::up = Axis(0, 90); +const Axis Axis::down = Axis(0, -90); +const Axis Axis::left = Axis(-90, 0); +const Axis Axis::right = Axis(90, 0); + +Vector3 Axis::ToVector3() { + Vector3 v = + Quaternion::Euler(-this->verticalAngle, this->horizontalAngle, 0) * + Vector3::forward; + return v; +} \ No newline at end of file diff --git a/Axis.h b/Axis.h new file mode 100644 index 0000000..992ab58 --- /dev/null +++ b/Axis.h @@ -0,0 +1,31 @@ +// 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/. + +#ifndef AXIS_H +#define AXIS_H + +#include "Angle.h" + +class Vector3; + +class Axis { +public: + Angle horizontalAngle; + Angle verticalAngle; + + Axis(); + Axis(Angle horizontal, Angle vertical); + Axis(Vector3 v); + + const static Axis forward; + const static Axis back; + const static Axis up; + const static Axis down; + const static Axis left; + const static Axis right; + + Vector3 ToVector3(); +}; + +#endif \ No newline at end of file From 64ca76830c81974eaac9b0d7edad631522a14b12 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 26 Apr 2024 12:12:22 +0200 Subject: [PATCH 031/121] normalize toAngleAxis result --- Quaternion.cpp | 61 ++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/Quaternion.cpp b/Quaternion.cpp index e621bb0..0389ab2 100644 --- a/Quaternion.cpp +++ b/Quaternion.cpp @@ -3,11 +3,11 @@ // file, You can obtain one at https ://mozilla.org/MPL/2.0/. #include "Quaternion.h" +#include "Vector3.h" #include #include -#include "Vector3.h" -void CopyQuat(const Quat& q1, Quat& q2) { +void CopyQuat(const Quat &q1, Quat &q2) { q2.x = q1.x; q2.y = q1.y; q2.z = q1.z; @@ -42,9 +42,7 @@ Quaternion::~Quaternion() {} const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1); -Vector3 Quaternion::xyz() const { - return Vector3(x, y, z); -} +Vector3 Quaternion::xyz() const { return Vector3(x, y, z); } float Quaternion::GetLength() const { return sqrtf(x * x + y * y + z * z + w * w); @@ -53,7 +51,7 @@ float Quaternion::GetLength() const { float Quaternion::GetLengthSquared() const { return x * x + y * y + z * z + w * w; } -float Quaternion::GetLengthSquared(const Quaternion& q) { +float Quaternion::GetLengthSquared(const Quaternion &q) { return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; } @@ -65,7 +63,7 @@ void Quaternion::Normalize() { w /= length; } -Quaternion Quaternion::Normalize(const Quaternion& q) { +Quaternion Quaternion::Normalize(const Quaternion &q) { Quaternion result; float length = q.GetLength(); result = Quaternion(q.x / length, q.y / length, q.z / length, q.w / length); @@ -76,11 +74,11 @@ float Quaternion::Dot(Quaternion a, Quaternion b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } -Vector3 Quaternion::ToAngles(const Quaternion& q1) { +Vector3 Quaternion::ToAngles(const Quaternion &q1) { float test = q1.x * q1.y + q1.z * q1.w; - if (test > 0.499f) { // singularity at north pole + if (test > 0.499f) { // singularity at north pole return Vector3(0, 2 * (float)atan2(q1.x, q1.w) * Rad2Deg, 90); - } else if (test < -0.499f) { // singularity at south pole + } else if (test < -0.499f) { // singularity at south pole return Vector3(0, -2 * (float)atan2(q1.x, q1.w) * Rad2Deg, -90); } else { float sqx = q1.x * q1.x; @@ -96,7 +94,7 @@ Vector3 Quaternion::ToAngles(const Quaternion& q1) { } } -Quaternion Quaternion::operator*(const Quaternion& r2) const { +Quaternion Quaternion::operator*(const Quaternion &r2) const { return Quaternion( this->x * r2.w + this->y * r2.z - this->z * r2.y + this->w * r2.x, -this->x * r2.z + this->y * r2.w + this->z * r2.x + this->w * r2.y, @@ -104,7 +102,7 @@ Quaternion Quaternion::operator*(const Quaternion& r2) const { -this->x * r2.x - this->y * r2.y - this->z * r2.z + this->w * r2.w); }; -Vector3 Quaternion::operator*(const Vector3& p) const { +Vector3 Quaternion::operator*(const Vector3 &p) const { float num = this->x * 2; float num2 = this->y * 2; float num3 = this->z * 2; @@ -127,7 +125,7 @@ Vector3 Quaternion::operator*(const Vector3& p) const { return result; } -bool Quaternion::operator==(const Quaternion& q) { +bool Quaternion::operator==(const Quaternion &q) { return (this->x == q.x && this->y == q.y && this->z == q.z && this->w == q.w); } @@ -136,11 +134,11 @@ Quaternion Quaternion::Inverse(Quaternion r) { return Quaternion(-r.x / n, -r.y / n, -r.z / n, r.w / n); } -Quaternion Quaternion::LookRotation(const Vector3& forward) { +Quaternion Quaternion::LookRotation(const Vector3 &forward) { Vector3 up = Vector3(0, 1, 0); return LookRotation(forward, up); } -Quaternion Quaternion::LookRotation(const Vector3& forward, const Vector3& up) { +Quaternion Quaternion::LookRotation(const Vector3 &forward, const Vector3 &up) { Vector3 nForward = Vector3::Normalize(forward); Vector3 nRight = Vector3::Normalize(Vector3::Cross(up, nForward)); Vector3 nUp = Vector3::Cross(nForward, nRight); @@ -201,8 +199,8 @@ Quaternion Quaternion::FromToRotation(Vector3 fromDirection, return rotation; } -Quaternion Quaternion::RotateTowards(const Quaternion& from, - const Quaternion& to, +Quaternion Quaternion::RotateTowards(const Quaternion &from, + const Quaternion &to, float maxDegreesDelta) { float num = Quaternion::Angle(from, to); if (num == 0) { @@ -212,7 +210,7 @@ Quaternion Quaternion::RotateTowards(const Quaternion& from, return SlerpUnclamped(from, to, t); } -Quaternion Quaternion::AngleAxis(float angle, const Vector3& axis) { +Quaternion Quaternion::AngleAxis(float angle, const Vector3 &axis) { if (Vector3::SqrMagnitude(axis) == 0.0f) return Quaternion(); @@ -234,27 +232,25 @@ float Quaternion::Angle(Quaternion a, Quaternion b) { return (float)acos(fmin(fabs(f), 1)) * 2 * Rad2Deg; } -void Quaternion::ToAngleAxis(float* angle, Vector3* axis) { +void Quaternion::ToAngleAxis(float *angle, Vector3 *axis) { Quaternion::ToAxisAngleRad(*this, axis, angle); *angle *= Rad2Deg; } -void Quaternion::ToAxisAngleRad(const Quaternion& q, - Vector3* const axis, - float* angle) { +void Quaternion::ToAxisAngleRad(const Quaternion &q, Vector3 *const axis, + float *angle) { Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q; - *angle = 2.0f * acosf(q1.w); // angle + *angle = 2.0f * acosf(q1.w); // angle float den = sqrtf(1.0F - q1.w * q1.w); if (den > 0.0001f) { - *axis = q1.xyz() / den; + *axis = Vector3::Normalize(q1.xyz() / den); } else { // This occurs when the angle is zero. // Not a problem: just set an arbitrary normalized axis. *axis = Vector3(1, 0, 0); } } -Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, - const Quaternion& b, +Quaternion Quaternion::SlerpUnclamped(const Quaternion &a, const Quaternion &b, float t) { // if either input is zero, return the other. if (Quaternion::GetLengthSquared(a) == 0.0f) { @@ -304,8 +300,7 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, return Quaternion(); } -Quaternion Quaternion::Slerp(const Quaternion& a, - const Quaternion& b, +Quaternion Quaternion::Slerp(const Quaternion &a, const Quaternion &b, float t) { if (t > 1) t = 1; @@ -391,18 +386,16 @@ float Quaternion::GetAngleAround(Vector3 axis, Quaternion rotation) { } Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) { - Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis + Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis Vector3 p = Vector3::Project( - ra, axis); // return projection ra on to axis (parallel component) + ra, axis); // return projection ra on to axis (parallel component) Quaternion twist = Quaternion(p.x, p.y, p.z, rotation.w); twist = Quaternion::Normalize(twist); return twist; } -void Quaternion::GetSwingTwist(Vector3 axis, - Quaternion rotation, - Quaternion* swing, - Quaternion* twist) { +void Quaternion::GetSwingTwist(Vector3 axis, Quaternion rotation, + Quaternion *swing, Quaternion *twist) { *twist = GetRotationAround(axis, rotation); *swing = rotation * Quaternion::Inverse(*twist); } From 8e7a8c64322148d2d7054879d34bc63aea84c504 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 10 May 2024 17:50:11 +0200 Subject: [PATCH 032/121] Fix namespaces --- Angle16.h | 5 +++++ Angle32.h | 4 ++++ Angle8.h | 5 +++++ AngleAxis.h | 4 ++++ AngleUsing.h | 4 ++++ Axis.h | 4 ++++ FloatSingle.h | 11 +++++++--- Matrix.h | 4 ++++ Polar.h | 12 ++++++++--- Quaternion.h | 56 ++++++++++++++++++++++++++------------------------- Range.h | 4 ++++ Spherical.cpp | 40 ++++++++++++++++++------------------ Spherical.h | 12 +++++------ Vector2.h | 13 ++++++++++-- Vector3.cpp | 20 ++++++++++++++++++ Vector3.h | 10 +++++++++ 16 files changed, 147 insertions(+), 61 deletions(-) diff --git a/Angle16.h b/Angle16.h index fd62d1d..47d31ce 100644 --- a/Angle16.h +++ b/Angle16.h @@ -3,6 +3,8 @@ #include "Angle.h" #include +namespace Passer { + typedef AngleUsing Angle16; template <> Angle16::AngleUsing(float angle) { @@ -19,3 +21,6 @@ template <> float Angle16::ToFloat() const { float f = ((this->value * 180) / 32768.0F); return f; } + +} // namespace Passer +using namespace Passer; \ No newline at end of file diff --git a/Angle32.h b/Angle32.h index 7d8ce10..cded359 100644 --- a/Angle32.h +++ b/Angle32.h @@ -3,6 +3,7 @@ #include "Angle.h" #include +namespace Passer { typedef AngleUsing Angle32; template <> Angle32::AngleUsing(float angle) { @@ -19,3 +20,6 @@ template <> float Angle32::ToFloat() const { float f = ((this->value * 180) / 2147483648.0F); return f; } + +} // namespace Passer +using namespace Passer; \ No newline at end of file diff --git a/Angle8.h b/Angle8.h index 22c8745..5ba5f6e 100644 --- a/Angle8.h +++ b/Angle8.h @@ -3,6 +3,8 @@ #include "Angle.h" #include +namespace Passer { + typedef AngleUsing Angle8; template <> Angle8::AngleUsing(float angle) { @@ -20,3 +22,6 @@ template <> float Angle8::ToFloat() const { float f = (this->value * 180) / 128.0F; return f; } + +} // namespace Passer +using namespace Passer; \ No newline at end of file diff --git a/AngleAxis.h b/AngleAxis.h index 68eda55..b387521 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -8,6 +8,8 @@ #include "Angle.h" #include "Axis.h" +namespace Passer { + class AngleAxis { public: Angle angle; @@ -16,5 +18,7 @@ public: AngleAxis(); AngleAxis(Angle angle, Axis axis); }; +} // namespace Passer +using namespace Passer; #endif \ No newline at end of file diff --git a/AngleUsing.h b/AngleUsing.h index 156fd6e..ca179db 100644 --- a/AngleUsing.h +++ b/AngleUsing.h @@ -4,6 +4,8 @@ #include "Angle.h" #include "Range.h" +namespace Passer { + // A fixed angle between (-180..180] template class AngleUsing { @@ -38,5 +40,7 @@ public: // protected: T value; }; +} // namespace Passer +using namespace Passer; #endif diff --git a/Axis.h b/Axis.h index 992ab58..0325257 100644 --- a/Axis.h +++ b/Axis.h @@ -7,6 +7,8 @@ #include "Angle.h" +namespace Passer { + class Vector3; class Axis { @@ -27,5 +29,7 @@ public: Vector3 ToVector3(); }; +} // namespace Passer +using namespace Passer; #endif \ No newline at end of file diff --git a/FloatSingle.h b/FloatSingle.h index 7aa2251..8922f06 100644 --- a/FloatSingle.h +++ b/FloatSingle.h @@ -5,11 +5,16 @@ #ifndef FLOAT_H #define FLOAT_H +namespace Passer { + class Float { public: - static const float epsilon; - static const float sqrEpsilon; + static const float epsilon; + static const float sqrEpsilon; - static float Clamp(float f, float min, float max); + static float Clamp(float f, float min, float max); }; +} // namespace Passer +using namespace Passer; + #endif diff --git a/Matrix.h b/Matrix.h index 7eb80a9..3997464 100644 --- a/Matrix.h +++ b/Matrix.h @@ -3,6 +3,8 @@ #include "Vector3.h" +namespace Passer { + /// @brief Single precision float matrix template class MatrixOf { public: @@ -110,5 +112,7 @@ private: unsigned int cols; T *data; }; +} // namespace Passer +using namespace Passer; #endif \ No newline at end of file diff --git a/Polar.h b/Polar.h index 78d2b69..9e2c8ca 100644 --- a/Polar.h +++ b/Polar.h @@ -5,10 +5,9 @@ #ifndef POLAR_H #define POLAR_H -struct Vector2; - namespace Passer { +struct Vector2; struct Spherical; /// @@ -40,8 +39,16 @@ public: /// The distance in meters Polar(float angle, float distance); + /// + /// Convert a Vector2 to a Polar coordinate + /// + /// The 2D carthesian vector Polar(Vector2 v); + /// + /// Convert a Spherical coordinate to a Polar coordinate + /// + /// The spherical coordinate Polar(Spherical s); /// @@ -54,7 +61,6 @@ public: /// /// This will rotate the vector by 180 degrees. Distance will stay the same. /// The negated vector - Polar operator-(); /// /// Substract a polar vector from this coordinate diff --git a/Quaternion.h b/Quaternion.h index eb40a5d..079128f 100644 --- a/Quaternion.h +++ b/Quaternion.h @@ -7,6 +7,8 @@ #include "Vector3.h" +namespace Passer { + extern "C" { /// /// A quaternion @@ -36,7 +38,7 @@ typedef struct Quat { /// A quaternion /// struct Quaternion : Quat { - public: +public: /// /// Create a new identity quaternion /// @@ -54,6 +56,9 @@ struct Quaternion : Quat { /// /// Quaternion(Quat q); + /// + /// Quaternion destructor + /// ~Quaternion(); /// @@ -74,7 +79,7 @@ struct Quaternion : Quat { /// A unit quaternion /// This will preserve the orientation, /// but ensures that it is a unit quaternion. - static Quaternion Normalize(const Quaternion& q); + static Quaternion Normalize(const Quaternion &q); /// /// Convert to euler angles @@ -82,14 +87,14 @@ struct Quaternion : Quat { /// The quaternion to convert /// A vector containing euler angles /// The euler angles performed in the order: Z, X, Y - static Vector3 ToAngles(const Quaternion& q); + static Vector3 ToAngles(const Quaternion &q); /// /// Rotate a vector using this quaterion /// /// The vector to rotate /// The rotated vector - Vector3 operator*(const Vector3& vector) const; + Vector3 operator*(const Vector3 &vector) const; /// /// Multiply this quaternion with another quaternion /// @@ -97,7 +102,7 @@ struct Quaternion : Quat { /// The resulting rotation /// The result will be this quaternion rotated according to /// the give rotation. - Quaternion operator*(const Quaternion& rotation) const; + Quaternion operator*(const Quaternion &rotation) const; /// /// Check the equality of two quaternions @@ -108,7 +113,7 @@ struct Quaternion : Quat { /// themselves. Two quaternions with the same rotational effect may have /// different components. Use Quaternion::Angle to check if the rotations are /// the same. - bool operator==(const Quaternion& quaternion); + bool operator==(const Quaternion &quaternion); /// /// The inverse of quaterion @@ -123,8 +128,8 @@ struct Quaternion : Quat { /// The look direction /// The up direction /// The look rotation - static Quaternion LookRotation(const Vector3& forward, - const Vector3& upwards); + static Quaternion LookRotation(const Vector3 &forward, + const Vector3 &upwards); /// /// Creates a quaternion with the given forward direction with up = /// Vector3::up @@ -134,7 +139,7 @@ struct Quaternion : Quat { /// For the rotation, Vector::up is used for the up direction. /// Note: if the forward direction == Vector3::up, the result is /// Quaternion::identity - static Quaternion LookRotation(const Vector3& forward); + static Quaternion LookRotation(const Vector3 &forward); /// /// Calculat the rotation from on vector to another @@ -151,8 +156,7 @@ struct Quaternion : Quat { /// The destination rotation /// The maximum amount of degrees to /// rotate The possibly limited rotation - static Quaternion RotateTowards(const Quaternion& from, - const Quaternion& to, + static Quaternion RotateTowards(const Quaternion &from, const Quaternion &to, float maxDegreesDelta); /// @@ -161,13 +165,13 @@ struct Quaternion : Quat { /// The angle /// The axis /// The resulting quaternion - static Quaternion AngleAxis(float angle, const Vector3& axis); + static Quaternion AngleAxis(float angle, const Vector3 &axis); /// /// Convert this quaternion to angle/axis representation /// /// A pointer to the angle for the result /// A pointer to the axis for the result - void ToAngleAxis(float* angle, Vector3* axis); + void ToAngleAxis(float *angle, Vector3 *axis); /// /// Get the angle between two orientations @@ -185,9 +189,8 @@ struct Quaternion : Quat { /// The factor between 0 and 1. /// The resulting rotation /// A factor 0 returns rotation1, factor1 returns rotation2. - static Quaternion Slerp(const Quaternion& rotation1, - const Quaternion& rotation2, - float factor); + static Quaternion Slerp(const Quaternion &rotation1, + const Quaternion &rotation2, float factor); /// /// Unclamped sherical lerp between two rotations /// @@ -197,9 +200,8 @@ struct Quaternion : Quat { /// The resulting rotation /// A factor 0 returns rotation1, factor1 returns rotation2. /// Values outside the 0..1 range will result in extrapolated rotations - static Quaternion SlerpUnclamped(const Quaternion& rotation1, - const Quaternion& rotation2, - float factor); + static Quaternion SlerpUnclamped(const Quaternion &rotation1, + const Quaternion &rotation2, float factor); /// /// Create a rotation from euler angles @@ -257,10 +259,8 @@ struct Quaternion : Quat { /// A pointer to the quaternion for the swing /// result A pointer to the quaternion for the /// twist result - static void GetSwingTwist(Vector3 axis, - Quaternion rotation, - Quaternion* swing, - Quaternion* twist); + static void GetSwingTwist(Vector3 axis, Quaternion rotation, + Quaternion *swing, Quaternion *twist); /// /// Calculate the dot product of two quaternions @@ -270,16 +270,18 @@ struct Quaternion : Quat { /// static float Dot(Quaternion rotation1, Quaternion rotation2); - private: +private: float GetLength() const; float GetLengthSquared() const; - static float GetLengthSquared(const Quaternion& q); + static float GetLengthSquared(const Quaternion &q); - void ToAxisAngleRad(const Quaternion& q, Vector3* const axis, float* angle); + void ToAxisAngleRad(const Quaternion &q, Vector3 *const axis, float *angle); static Quaternion FromEulerRad(Vector3 euler); static Quaternion FromEulerRadXYZ(Vector3 euler); Vector3 xyz() const; }; +} // namespace Passer +using namespace Passer; -#endif \ No newline at end of file +#endif diff --git a/Range.h b/Range.h index bf632ae..59ac3f5 100644 --- a/Range.h +++ b/Range.h @@ -1,6 +1,8 @@ #ifndef RANGE_H #define RANGE_H +namespace Passer { + /* /// @brief Signed range. May be renamed to SignedRange later class Range16 { @@ -39,5 +41,7 @@ public: T value; }; +} // namespace Passer +using namespace Passer; #endif \ No newline at end of file diff --git a/Spherical.cpp b/Spherical.cpp index 2449a6c..4abebbb 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -36,25 +36,25 @@ Spherical::Spherical(Vector3 v) { const Spherical Spherical::zero = Spherical(0.0F, (Angle)0.0F, (Angle)0.0F); -float Spherical::GetSwing() { - // Not sure if this is correct - return sqrtf(horizontalAngle * horizontalAngle + - verticalAngle * verticalAngle); -} +// float Spherical::GetSwing() { +// // Not sure if this is correct +// return sqrtf(horizontalAngle * horizontalAngle + +// verticalAngle * verticalAngle); +// } -Polar Spherical::ProjectOnHorizontalPlane() { - return Polar(horizontalAngle, distance); -} +// Polar Spherical::ProjectOnHorizontalPlane() { +// return Polar(horizontalAngle, distance); +// } -Vector3 Spherical::ToVector3() { - float verticalRad = (90 - verticalAngle) * Angle::Deg2Rad; - float horizontalRad = horizontalAngle * Angle::Deg2Rad; - float cosVertical = cosf(verticalRad); - float sinVertical = sinf(verticalRad); - float cosHorizontal = cosf(horizontalRad); - float sinHorizontal = sinf(horizontalRad); - Vector3 v = Vector3(this->distance * sinVertical * sinHorizontal, - this->distance * cosVertical, - this->distance * sinVertical * cosHorizontal); - return v; -} \ No newline at end of file +// Vector3 Spherical::ToVector3() { +// float verticalRad = (90 - verticalAngle) * Angle::Deg2Rad; +// float horizontalRad = horizontalAngle * Angle::Deg2Rad; +// float cosVertical = cosf(verticalRad); +// float sinVertical = sinf(verticalRad); +// float cosHorizontal = cosf(horizontalRad); +// float sinHorizontal = sinf(horizontalRad); +// Vector3 v = Vector3(this->distance * sinVertical * sinHorizontal, +// this->distance * cosVertical, +// this->distance * sinVertical * cosHorizontal); +// return v; +// } \ No newline at end of file diff --git a/Spherical.h b/Spherical.h index 8231507..db75845 100644 --- a/Spherical.h +++ b/Spherical.h @@ -9,10 +9,10 @@ #include "Angle.h" #include "Polar.h" -struct Vector3; - namespace Passer { +struct Vector3; + /// @brief A spherical vector /// @details /// This is a vector in 3D space using a spherical coordinate system. @@ -39,7 +39,6 @@ public: /// zero is forward, positive is upward /// @param distance The distance in meters // Spherical(float polarAngle, float elevationAngle, float distance); - Spherical(float distance, Angle horizontalAngle, Angle verticalAngle); /// @brief Convert polar coordinates to spherical coordinates @@ -53,10 +52,11 @@ public: /// @brief A spherical vector with zero degree angles and distance const static Spherical zero; - float GetSwing(); + // float GetSwing(); - Polar ProjectOnHorizontalPlane(); - Vector3 ToVector3(); + // Polar ProjectOnHorizontalPlane(); + + // Vector3 ToVector3(); }; } // namespace Passer diff --git a/Vector2.h b/Vector2.h index 4d88ed3..5986451 100644 --- a/Vector2.h +++ b/Vector2.h @@ -24,7 +24,9 @@ typedef struct Vec2 { } Vec2; } -class Vector3; +namespace Passer { + +struct Vector3; /// /// A 2-dimensional vector @@ -48,8 +50,15 @@ public: /// The C-style Vec Vector2(Vec2 v); + /// + /// Convert a Vector3 to a Vector3 + /// + /// The 3D vector Vector2(Vector3 v); + /// + /// Vector2 destructor + /// @@ -234,5 +243,5 @@ public: /// between *from* and *to* etc. static Vector2 Lerp(Vector2 from, Vector2 to, float f); }; - +} // namespace Passer #endif \ No newline at end of file diff --git a/Vector3.cpp b/Vector3.cpp index c08c1c0..3ee597e 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -3,6 +3,9 @@ // file, You can obtain one at https ://mozilla.org/MPL/2.0/. #include "Vector3.h" +#include "Angle.h" +#include "Spherical.h" + #include const float Deg2Rad = 0.0174532924F; @@ -27,6 +30,23 @@ Vector3::Vector3(Vec3 v) { z = v.z; } +Vector3::Vector3(Spherical s) { + float verticalRad = (90 - s.verticalAngle) * Angle::Deg2Rad; + float horizontalRad = s.horizontalAngle * Angle::Deg2Rad; + float cosVertical = cosf(verticalRad); + float sinVertical = sinf(verticalRad); + float cosHorizontal = cosf(horizontalRad); + float sinHorizontal = sinf(horizontalRad); + + x = s.distance * sinVertical * sinHorizontal; + y = s.distance * cosVertical; + z = s.distance * sinVertical * cosHorizontal; + // Vector3 v = Vector3(s.distance * sinVertical * sinHorizontal, + // s.distance * cosVertical, + // ); + // return v; +} + Vector3::~Vector3() {} const Vector3 Vector3::zero = Vector3(0, 0, 0); diff --git a/Vector3.h b/Vector3.h index 50fc1f3..13d2aa0 100644 --- a/Vector3.h +++ b/Vector3.h @@ -7,6 +7,10 @@ #include "Vector2.h" +namespace Passer { + +struct Spherical; + extern "C" { /// /// 3-dimensional Vector representation @@ -52,6 +56,10 @@ public: /// /// The C-style Vec Vector3(Vec3 v); + /// + /// Vector3 destructor + /// + Vector3(Spherical s); ~Vector3(); /// @@ -267,5 +275,7 @@ public: /// between *from* and *to* etc. static Vector3 Lerp(const Vector3 &from, const Vector3 &to, float f); }; +} // namespace Passer +using namespace Passer; #endif \ No newline at end of file From e5f8d73e19976f4f3f3887f53e44400f246a5a2e Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 10 May 2024 18:01:42 +0200 Subject: [PATCH 033/121] namespace fix --- Angle.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Angle.h b/Angle.h index edabf65..6f130ff 100644 --- a/Angle.h +++ b/Angle.h @@ -5,6 +5,8 @@ #ifndef ANGLE_H #define ANGLE_H +namespace Passer { + template class Angle2 { public: Angle2(){}; @@ -52,4 +54,7 @@ public: static float SineRuleAngle(float a, float beta, float c); }; */ +} // namespace Passer +using namespace Passer; + #endif \ No newline at end of file From 8a2ce21abc55c0932b0af49d93a8416b8c1b6d96 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 10 May 2024 18:01:54 +0200 Subject: [PATCH 034/121] Swapped polar constructor param order --- Polar.cpp | 26 ++++++++++++++++++-------- Polar.h | 5 ++++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index 421962e..acdd506 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -9,7 +9,8 @@ Polar::Polar() { distance = 0.0F; } -Polar::Polar(float newAngle, float newDistance) { +// Polar::Polar(float newAngle, float newDistance) { +Polar::Polar(float newDistance, Angle newAngle) { // distance should always be 0 or greater if (newDistance < 0) { angle = Angle::Normalize(newAngle - 180); @@ -42,7 +43,8 @@ float Polar::Distance(const Polar &v1, const Polar &v2) { Polar Polar::operator+(const Polar &v2) const { if (v2.distance == 0) - return Polar(this->angle, this->distance); + return Polar(this->distance, + this->angle); // Polar(this->angle, this->distance); if (this->distance == 0) return v2; @@ -51,7 +53,9 @@ Polar Polar::operator+(const Polar &v2) const { if (rotation == 180 && v2.distance > 0) { // angle is too small, take this angle and add the distances - return Polar(this->angle, this->distance + v2.distance); + return Polar( + this->distance + v2.distance, + this->angle); // Polar(this->angle, this->distance + v2.distance); } float newDistance = @@ -62,26 +66,32 @@ Polar Polar::operator+(const Polar &v2) const { float newAngle = deltaAngle < 0 ? Angle::Normalize(this->angle - angle) : Angle::Normalize(this->angle + angle); - Polar vector = Polar(newAngle, newDistance); + Polar vector = Polar(newDistance, newAngle); // Polar(newAngle, newDistance); return vector; } Polar Polar::operator-() { - Polar vector = Polar(this->angle - 180, this->distance); + Polar vector = + Polar(this->distance, + this->angle - 180); // Polar(this->angle - 180, this->distance); return vector; } Polar Polar::operator-(const Polar &v2) const { - Polar vector = *this + (Polar(v2.angle - 180, v2.distance)); + Polar vector = + *this + Polar(v2.distance, + v2.angle - 180); //(Polar(v2.angle - 180, v2.distance)); return vector; } Polar Polar::operator*(float f) const { - return Polar(this->angle, this->distance * f); + return Polar(this->distance * f, + this->angle); // Polar(this->angle, this->distance * f); } Polar Polar::operator/(const float &f) { - return Polar(this->angle, this->distance / f); + return Polar(this->distance / f, + this->angle); // Polar(this->angle, this->distance / f); } Polar Polar::Rotate(Polar v, float angle) { diff --git a/Polar.h b/Polar.h index 9e2c8ca..43b6c08 100644 --- a/Polar.h +++ b/Polar.h @@ -5,6 +5,8 @@ #ifndef POLAR_H #define POLAR_H +#include "Angle.h" + namespace Passer { struct Vector2; @@ -37,7 +39,8 @@ public: /// /// The angle in degrees, clockwise rotation /// The distance in meters - Polar(float angle, float distance); + // Polar(float angle, float distance); + Polar(float distance, Angle angle); /// /// Convert a Vector2 to a Polar coordinate From 9bea94f21c3e7082a4aab360410753ab669ff9a5 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 10 May 2024 18:18:33 +0200 Subject: [PATCH 035/121] Use Angle type for Polar --- Polar.cpp | 33 +++++++++++++++++---------------- Polar.h | 10 +++++----- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index acdd506..c12ae96 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -35,20 +35,20 @@ Polar::Polar(Spherical s) { const Polar Polar::zero = Polar(0, 0); -float Polar::Distance(const Polar &v1, const Polar &v2) { - float d = - Angle::CosineRuleSide(v1.distance, v2.distance, v2.angle - v1.angle); +float Polar::Distance(Polar &v1, Polar &v2) { + float d = Angle::CosineRuleSide(v1.distance, v2.distance, + (float)v2.angle - (float)v1.angle); return d; } -Polar Polar::operator+(const Polar &v2) const { +Polar Polar::operator+(Polar &v2) { if (v2.distance == 0) return Polar(this->distance, this->angle); // Polar(this->angle, this->distance); if (this->distance == 0) return v2; - float deltaAngle = Angle::Normalize(v2.angle - this->angle); + float deltaAngle = Angle::Normalize(v2.angle - (float)this->angle); float rotation = deltaAngle < 0 ? 180 + deltaAngle : 180 - deltaAngle; if (rotation == 180 && v2.distance > 0) { @@ -64,24 +64,25 @@ Polar Polar::operator+(const Polar &v2) const { float angle = Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); - float newAngle = deltaAngle < 0 ? Angle::Normalize(this->angle - angle) - : Angle::Normalize(this->angle + angle); + float newAngle = + deltaAngle < 0 ? (float)this->angle - angle : (float)this->angle + angle; + newAngle = Angle::Normalize(newAngle); Polar vector = Polar(newDistance, newAngle); // Polar(newAngle, newDistance); return vector; } Polar Polar::operator-() { - Polar vector = - Polar(this->distance, - this->angle - 180); // Polar(this->angle - 180, this->distance); + Polar vector = Polar(this->distance, + (float)this->angle - + 180); // Polar(this->angle - 180, this->distance); return vector; } -Polar Polar::operator-(const Polar &v2) const { - Polar vector = - *this + Polar(v2.distance, - v2.angle - 180); //(Polar(v2.angle - 180, v2.distance)); - return vector; +Polar Polar::operator-(Polar &v2) { + // Polar vector = *this + Polar(v2.distance, (float)v2.angle - 180); + //(Polar(v2.angle - 180, v2.distance)); + Polar vector = -v2; + return *this + v2; } Polar Polar::operator*(float f) const { @@ -94,7 +95,7 @@ Polar Polar::operator/(const float &f) { this->angle); // Polar(this->angle, this->distance / f); } -Polar Polar::Rotate(Polar v, float angle) { +Polar Polar::Rotate(Polar v, Angle angle) { v.angle = Angle::Normalize(v.angle + angle); return v; } \ No newline at end of file diff --git a/Polar.h b/Polar.h index 43b6c08..c77bb05 100644 --- a/Polar.h +++ b/Polar.h @@ -23,7 +23,7 @@ public: /// The angle in degrees, clockwise rotation /// /// The angle is normalized to -180 .. 180 - float angle; + Angle angle; /// /// The distance in meters /// @@ -70,14 +70,14 @@ public: /// /// The vector to subtract from this vector /// The result of the subtraction - Polar operator-(const Polar &v) const; + Polar operator-(Polar &v); /// /// Add another polar vector to this polar vector /// /// The vector to add /// The result of adding the vector - Polar operator+(const Polar &v) const; + Polar operator+(Polar &v); /// /// Scale the vector uniformly up @@ -103,7 +103,7 @@ public: /// The first vector /// The second vector /// The distance between the two vectors - static float Distance(const Polar &v1, const Polar &v2); + static float Distance(Polar &v1, Polar &v2); /// /// Rotate the vector @@ -111,7 +111,7 @@ public: /// The vector to rotate /// Angle in radias to rotate /// The rotated vector - static Polar Rotate(Polar v, float angle); + static Polar Rotate(Polar v, Angle angle); }; } // namespace Passer #include "Spherical.h" From 791bd78e2909065f2f7e3bd47dbf3fce14c4286a Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 10 May 2024 18:19:10 +0200 Subject: [PATCH 036/121] namespace improvement --- Polar.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Polar.h b/Polar.h index c77bb05..36cadc9 100644 --- a/Polar.h +++ b/Polar.h @@ -114,6 +114,8 @@ public: static Polar Rotate(Polar v, Angle angle); }; } // namespace Passer +using namespace Passer; + #include "Spherical.h" #include "Vector2.h" From 3d971c115ed620fd9d2337e51ff83d0ae407aa9c Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 10 May 2024 18:24:41 +0200 Subject: [PATCH 037/121] Improve namespace --- Vector2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Vector2.h b/Vector2.h index 5986451..c95f0d5 100644 --- a/Vector2.h +++ b/Vector2.h @@ -244,4 +244,6 @@ public: static Vector2 Lerp(Vector2 from, Vector2 to, float f); }; } // namespace Passer +using namespace Passer; + #endif \ No newline at end of file From 5489b3c45cb2eded59262983c2a5f23340465f26 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 10 May 2024 18:24:51 +0200 Subject: [PATCH 038/121] Fix test --- test/Spherical_test.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 973bac0..75d7e95 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -33,7 +33,7 @@ TEST(Spherical, FromVector3) { TEST(Spherical, ToVector3) { Vector3 v = Vector3(0, 0, 1); Spherical s = Spherical(v); - Vector3 r = s.ToVector3(); + Vector3 r = Vector3(s); // s.ToVector3(); EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 0 1"; EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; @@ -41,7 +41,7 @@ TEST(Spherical, ToVector3) { v = Vector3(0, 1, 0); s = Spherical(v); - r = s.ToVector3(); + r = Vector3(s); // s.ToVector3(); EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 1 0"; EXPECT_FLOAT_EQ(r.y, 1.0F) << "toVector3.y 0 1 0"; @@ -49,7 +49,7 @@ TEST(Spherical, ToVector3) { v = Vector3(1, 0, 0); s = Spherical(v); - r = s.ToVector3(); + r = Vector3(s); // s.ToVector3(); EXPECT_FLOAT_EQ(r.x, 1.0F) << "toVector3.x 1 0 0"; EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; @@ -65,7 +65,7 @@ TEST(Spherical, Incident1) { EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-02); EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-02); - Vector3 r = sr.ToVector3(); + Vector3 r = Vector3(sr); // sr.ToVector3(); EXPECT_NEAR(r.x, v.x, 1.0e-02) << "toVector3.x 1 0 0"; EXPECT_NEAR(r.y, v.y, 1.0e-02) << "toVector3.y 1 0 0"; EXPECT_NEAR(r.z, v.z, 1.0e-02) << "toVector3.z 1 0 0"; @@ -80,7 +80,7 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); - Vector3 r = sr.ToVector3(); + Vector3 r = Vector3(sr); // sr.ToVector3(); EXPECT_NEAR(r.x, v.x, 1.0e-06); EXPECT_NEAR(r.y, v.y, 1.0e-06); EXPECT_NEAR(r.z, v.z, 1.0e-06); @@ -93,14 +93,14 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); - r = sr.ToVector3(); + r = Vector3(sr); // sr.ToVector3(); EXPECT_NEAR(r.x, v.x, 1.0e-06); EXPECT_NEAR(r.y, v.y, 1.0e-06); EXPECT_NEAR(r.z, v.z, 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); s = Spherical(v); - r = s.ToVector3(); + r = Vector3(s); // s.ToVector3(); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); From 6ddb07422589adadd628ffdf43a5e8728e53b995 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 13:48:03 +0200 Subject: [PATCH 039/121] Improved unit tests --- Polar.cpp | 13 +++++----- Spherical.cpp | 15 ++++++++--- Vector2.cpp | 9 +++++++ Vector2.h | 5 ++++ Vector3.h | 2 ++ test/Polar_test.cc | 42 ++++++++++++++++++++++++++++++ test/Spherical_test.cc | 58 +++++++++++++++++++++++++----------------- test/Vector2_test.cc | 27 ++++++++++++++++++++ test/Vector3_test.cc | 27 ++++++++++++++++++++ 9 files changed, 165 insertions(+), 33 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index c12ae96..76276f6 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -9,15 +9,14 @@ Polar::Polar() { distance = 0.0F; } -// Polar::Polar(float newAngle, float newDistance) { -Polar::Polar(float newDistance, Angle newAngle) { +Polar::Polar(float distance, Angle angle) { // distance should always be 0 or greater - if (newDistance < 0) { - angle = Angle::Normalize(newAngle - 180); - distance = -newDistance; + if (distance < 0) { + this->distance = -distance; + this->angle = Angle::Normalize(angle - 180); } else { - angle = Angle::Normalize(newAngle); - distance = newDistance; + this->distance = distance; + this->angle = Angle::Normalize(angle); } } diff --git a/Spherical.cpp b/Spherical.cpp index 4abebbb..0f9b2f5 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -19,9 +19,18 @@ Spherical::Spherical(Polar polar) { this->distance = polar.distance; } -Spherical::Spherical(float distance, Angle horizontalAngle, Angle verticalAngle) - : distance(distance), horizontalAngle(horizontalAngle), - verticalAngle(verticalAngle) {} +Spherical::Spherical(float distance, Angle horizontalAngle, + Angle verticalAngle) { + if (distance < 0) { + this->distance = -distance; + this->horizontalAngle = Angle::Normalize(horizontalAngle - 180); + this->verticalAngle = verticalAngle; + } else { + this->distance = distance; + this->horizontalAngle = Angle::Normalize(horizontalAngle); + this->verticalAngle = Angle::Normalize(verticalAngle); + } +} Spherical::Spherical(Vector3 v) { distance = v.magnitude(); diff --git a/Vector2.cpp b/Vector2.cpp index 2d1ff19..5a1495a 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -33,6 +33,15 @@ Vector2::Vector2(Vector3 v) { y = v.z; } +Vector2::Vector2(Polar p) { + float horizontalRad = p.angle * Angle::Deg2Rad; + float cosHorizontal = cosf(horizontalRad); + float sinHorizontal = sinf(horizontalRad); + + x = p.distance * sinHorizontal; + y = p.distance * cosHorizontal; +} + Vector2::~Vector2() {} const Vector2 Vector2::zero = Vector2(0, 0); diff --git a/Vector2.h b/Vector2.h index c95f0d5..19daeb1 100644 --- a/Vector2.h +++ b/Vector2.h @@ -27,6 +27,7 @@ typedef struct Vec2 { namespace Passer { struct Vector3; +struct Polar; /// /// A 2-dimensional vector @@ -56,6 +57,8 @@ public: /// The 3D vector Vector2(Vector3 v); + Vector2(Polar p); + /// /// Vector2 destructor /// ::infinity() +TEST(Vector2, FromPolar) { + Vector2 v; + Polar p; + Vector2 r; + + v = Vector2(0, 1); + p = Polar(v); + r = Vector2(p); + + EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 1)"; + EXPECT_FLOAT_EQ(r.y, 1.0F) << "FromPolar(0 1)"; + + v = Vector2(1, 0); + p = Polar(v); + r = Vector2(p); + + EXPECT_FLOAT_EQ(r.x, 1.0F) << "FromPolar(1 0)"; + EXPECT_NEAR(r.y, 0.0F, 1.0e-07) << "FromPolar(1 0)"; + + v = Vector2(0, 0); + p = Polar(v); + r = Vector2(p); + + EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 0)"; + EXPECT_FLOAT_EQ(r.y, 0.0F) << "FromPolar(0 0)"; +} + TEST(Vector2, Magnitude) { Vector2 v = Vector2(1, 2); float m = 0; diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index 2148937..483cbdb 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -7,6 +7,32 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() +TEST(Vector3, FromSpherical) { + Vector3 v = Vector3(0, 0, 1); + Spherical s = Spherical(v); + Vector3 r = Vector3(s); + + EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 0 1"; + EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; + EXPECT_FLOAT_EQ(r.z, 1.0F) << "toVector3.z 0 0 1"; + + v = Vector3(0, 1, 0); + s = Spherical(v); + r = Vector3(s); + + EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 1 0"; + EXPECT_FLOAT_EQ(r.y, 1.0F) << "toVector3.y 0 1 0"; + EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; + + v = Vector3(1, 0, 0); + s = Spherical(v); + r = Vector3(s); + + EXPECT_FLOAT_EQ(r.x, 1.0F) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; +} + TEST(Vector3, Magnitude) { Vector3 v = Vector3(1, 2, 3); float m = 0; @@ -550,4 +576,5 @@ TEST(Vector3, Lerp) { r = Vector3::Lerp(v1, v2, 2); EXPECT_FLOAT_EQ(Vector3::Distance(r, Vector3(-2.0, -1.0f, 0.0f)), 0); } + #endif \ No newline at end of file From b1e34b619ed03d001c3706d7cb03c2590b26e373 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 15:32:16 +0200 Subject: [PATCH 040/121] Improved unit tests --- Polar.cpp | 66 ++++++++++++++++++++++++---------------------- Polar.h | 61 ++++++++++++++++++------------------------ Spherical.cpp | 49 +++++++++++++++------------------- Spherical.h | 31 +++++++++++++--------- test/Polar_test.cc | 24 +++++++++++++++++ 5 files changed, 123 insertions(+), 108 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index 76276f6..5332b24 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -5,56 +5,54 @@ #include "Spherical.h" Polar::Polar() { - angle = 0.0F; - distance = 0.0F; + this->distance = 0.0f; + this->angle = 0.0f; } Polar::Polar(float distance, Angle angle) { // distance should always be 0 or greater - if (distance < 0) { + if (distance < 0.0f) { this->distance = -distance; this->angle = Angle::Normalize(angle - 180); } else { this->distance = distance; - this->angle = Angle::Normalize(angle); + if (this->distance == 0.0f) + // angle is always 0 if distance is 0 + this->angle = 0.0f; + else + this->angle = Angle::Normalize(angle); } } Polar::Polar(Vector2 v) { - angle = Vector2::SignedAngle( - Vector2::forward, - v); // atan2(v.x, sqrt(v.z * v.z + v.y * v.y)) * Angle::Rad2Deg; - distance = v.magnitude(); + this->distance = v.magnitude(); + this->angle = Vector2::SignedAngle(Vector2::forward, v); } -Polar::Polar(Spherical s) { - angle = s.horizontalAngle; - distance = s.distance * cosf(s.verticalAngle * Angle::Deg2Rad); +Polar::Polar(Spherical v) { + this->distance = v.distance * cosf(v.verticalAngle * Angle::Deg2Rad); + this->angle = v.horizontalAngle; } -const Polar Polar::zero = Polar(0, 0); +const Polar Polar::zero = Polar(0.0f, 0.0f); -float Polar::Distance(Polar &v1, Polar &v2) { - float d = Angle::CosineRuleSide(v1.distance, v2.distance, - (float)v2.angle - (float)v1.angle); - return d; +bool Polar::operator==(const Polar &v) { + return (this->distance == v.distance && this->angle == v.angle); } Polar Polar::operator+(Polar &v2) { if (v2.distance == 0) - return Polar(this->distance, - this->angle); // Polar(this->angle, this->distance); - if (this->distance == 0) + return Polar(this->distance, this->angle); + if (this->distance == 0.0f) return v2; float deltaAngle = Angle::Normalize(v2.angle - (float)this->angle); - float rotation = deltaAngle < 0 ? 180 + deltaAngle : 180 - deltaAngle; + float rotation = + deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle; - if (rotation == 180 && v2.distance > 0) { + if (rotation == 180.0f && v2.distance > 0.0f) { // angle is too small, take this angle and add the distances - return Polar( - this->distance + v2.distance, - this->angle); // Polar(this->angle, this->distance + v2.distance); + return Polar(this->distance + v2.distance, this->angle); } float newDistance = @@ -63,24 +61,22 @@ Polar Polar::operator+(Polar &v2) { float angle = Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); - float newAngle = - deltaAngle < 0 ? (float)this->angle - angle : (float)this->angle + angle; + float newAngle = deltaAngle < 0.0f ? (float)this->angle - angle + : (float)this->angle + angle; newAngle = Angle::Normalize(newAngle); - Polar vector = Polar(newDistance, newAngle); // Polar(newAngle, newDistance); + Polar vector = Polar(newDistance, newAngle); return vector; } Polar Polar::operator-() { - Polar vector = Polar(this->distance, - (float)this->angle - - 180); // Polar(this->angle - 180, this->distance); - return vector; + Polar v = Polar(this->distance, this->angle + 180); + return v; } Polar Polar::operator-(Polar &v2) { // Polar vector = *this + Polar(v2.distance, (float)v2.angle - 180); //(Polar(v2.angle - 180, v2.distance)); - Polar vector = -v2; + v2 = -v2; return *this + v2; } @@ -94,6 +90,12 @@ Polar Polar::operator/(const float &f) { this->angle); // Polar(this->angle, this->distance / f); } +float Polar::Distance(Polar &v1, Polar &v2) { + float d = Angle::CosineRuleSide(v1.distance, v2.distance, + (float)v2.angle - (float)v1.angle); + return d; +} + Polar Polar::Rotate(Polar v, Angle angle) { v.angle = Angle::Normalize(v.angle + angle); return v; diff --git a/Polar.h b/Polar.h index 36cadc9..9fdb50e 100644 --- a/Polar.h +++ b/Polar.h @@ -19,57 +19,48 @@ struct Spherical; /// reference direction and a distance. struct Polar { public: - /// - /// The angle in degrees, clockwise rotation - /// - /// The angle is normalized to -180 .. 180 - Angle angle; /// /// The distance in meters /// /// The distance should never be negative + + /// @brief The distance in meters + /// @remark The distance shall never be negative float distance; + /// @brief The angle in degrees clockwise rotation + /// @remark The angle shall be between -180 .. 180 + Angle angle; - /// - /// Create a new polar vector with zero degrees and distance - /// + /// @brief A new vector with polar coordinates with zero degrees and distance Polar(); - /// - /// Create a new polar vector - /// - /// The angle in degrees, clockwise rotation - /// The distance in meters - // Polar(float angle, float distance); + /// @brief A new vector with polar coordinates + /// @param distance The distance in meters + /// @param angle The angle in degrees, clockwise rotation + /// @note The distance is automatically converted to a positive value. + /// @note The angle is automatically normalized to -180 .. 180 Polar(float distance, Angle angle); - - /// - /// Convert a Vector2 to a Polar coordinate - /// - /// The 2D carthesian vector + /// @brief Convert a vector from 2D carthesian coordinates to polar + /// coordinates + /// @param v The vector to convert Polar(Vector2 v); - /// - /// Convert a Spherical coordinate to a Polar coordinate - /// - /// The spherical coordinate + /// @brief Convert a vector from spherical coordinates to polar coordinates + /// @param s The vector to convert + /// @note The resulting vector will be projected on the horizontal plane Polar(Spherical s); - /// - /// A polar vector with zero degrees and distance - /// + /// @brief A polar vector with zero degrees and distance const static Polar zero; - /// - /// Negate the polar vector. - /// + bool operator==(const Polar &v); + + /// @brief Negate the vector + /// @return The negated vector /// This will rotate the vector by 180 degrees. Distance will stay the same. - /// The negated vector Polar operator-(); - /// - /// Substract a polar vector from this coordinate - /// - /// The vector to subtract from this vector - /// The result of the subtraction + /// @brief Subtract a polar vector from this vector + /// @param v The vector to subtract + /// @return The result of the subtraction Polar operator-(Polar &v); /// diff --git a/Spherical.cpp b/Spherical.cpp index 0f9b2f5..699d01e 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -5,18 +5,16 @@ #include -// using Angle = float; - Spherical::Spherical() { - this->horizontalAngle = 0; - this->verticalAngle = 0; - this->distance = 0; + this->distance = 0.0f; + this->horizontalAngle = 0.0f; + this->verticalAngle = 0.0f; } Spherical::Spherical(Polar polar) { - this->horizontalAngle = polar.angle; - this->verticalAngle = 0.0F; this->distance = polar.distance; + this->horizontalAngle = polar.angle; + this->verticalAngle = 0.0f; } Spherical::Spherical(float distance, Angle horizontalAngle, @@ -33,17 +31,24 @@ Spherical::Spherical(float distance, Angle horizontalAngle, } Spherical::Spherical(Vector3 v) { - distance = v.magnitude(); + this->distance = v.magnitude(); if (distance == 0.0f) { - verticalAngle = 0; - horizontalAngle = 0; + this->verticalAngle = 0.0f; + this->horizontalAngle = 0.0f; } else { - verticalAngle = (90 - acosf(v.y / distance) * Angle::Rad2Deg); - horizontalAngle = atan2f(v.x, v.z) * Angle::Rad2Deg; + this->verticalAngle = + (90.0f - acosf(v.y / this->distance) * Angle::Rad2Deg); + this->horizontalAngle = atan2f(v.x, v.z) * Angle::Rad2Deg; } } -const Spherical Spherical::zero = Spherical(0.0F, (Angle)0.0F, (Angle)0.0F); +const Spherical Spherical::zero = Spherical(0.0f, 0.0f, 0.0f); + +Spherical Spherical::operator-() { + Spherical v = Spherical(this->distance, this->horizontalAngle + 180.0f, + this->verticalAngle + 180.0f); + return v; +} // float Spherical::GetSwing() { // // Not sure if this is correct @@ -51,19 +56,7 @@ const Spherical Spherical::zero = Spherical(0.0F, (Angle)0.0F, (Angle)0.0F); // verticalAngle * verticalAngle); // } -// Polar Spherical::ProjectOnHorizontalPlane() { -// return Polar(horizontalAngle, distance); -// } - -// Vector3 Spherical::ToVector3() { -// float verticalRad = (90 - verticalAngle) * Angle::Deg2Rad; -// float horizontalRad = horizontalAngle * Angle::Deg2Rad; -// float cosVertical = cosf(verticalRad); -// float sinVertical = sinf(verticalRad); -// float cosHorizontal = cosf(horizontalRad); -// float sinHorizontal = sinf(horizontalRad); -// Vector3 v = Vector3(this->distance * sinVertical * sinHorizontal, -// this->distance * cosVertical, -// this->distance * sinVertical * cosHorizontal); -// return v; +// float Spherical::Distance(const Spherical &s1, const Spherical &s2) { +// float d = 0; +// return d; // } \ No newline at end of file diff --git a/Spherical.h b/Spherical.h index db75845..9e9c73c 100644 --- a/Spherical.h +++ b/Spherical.h @@ -1,4 +1,3 @@ -/// @copyright /// 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/. @@ -21,8 +20,9 @@ struct Vector3; /// as a forward direction. struct Spherical { public: + /// @brief The distance in meters + /// @remark The distance should never be negative float distance; - /// @brief The angle in the horizontal plane in degrees, clockwise rotation /// @details The angle is automatically normalized to -180 .. 180 Angle horizontalAngle; @@ -33,18 +33,15 @@ public: /// @brief Create a new spherical vector with zero degrees and distance Spherical(); /// @brief Create a new spherical vector - /// @param polarAngle The angle in the horizontal plane in degrees, - /// clockwise rotation - /// @param elevationAngle The angle in the vertical plan in degrees, - /// zero is forward, positive is upward /// @param distance The distance in meters - // Spherical(float polarAngle, float elevationAngle, float distance); + /// @param horizontalAngle The angle in the horizontal plane in degrees, + /// clockwise rotation + /// @param verticalAngle The angle in the vertical plan in degrees, + /// zero is forward, positive is upward Spherical(float distance, Angle horizontalAngle, Angle verticalAngle); - /// @brief Convert polar coordinates to spherical coordinates /// @param polar The polar coordinate Spherical(Polar polar); - /// @brief Convert 3D carthesian coordinates to spherical coordinates /// @param v Vector in 3D carthesian coordinates; Spherical(Vector3 v); @@ -52,11 +49,19 @@ public: /// @brief A spherical vector with zero degree angles and distance const static Spherical zero; - // float GetSwing(); + /// @brief Negate the vector + /// @return The negated vector + /// This will rotate the vector by 180 degrees horizontally and + /// vertically. Distance will stay the same. + Spherical operator-(); - // Polar ProjectOnHorizontalPlane(); - - // Vector3 ToVector3(); + /// + /// The distance between two vectors + /// + /// The first vector + /// The second vector + /// The distance between the two vectors + // static float Distance(const Spherical &s1, const Spherical &s2); }; } // namespace Passer diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 8afe2c3..bd1a3b4 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -68,4 +68,28 @@ TEST(Polar, FromSpherical) { EXPECT_FLOAT_EQ(p.angle, 0.0F) << "p.angle FromSpherical(0 0 90)"; } +TEST(Polar, Negate) { + Polar v = Polar(2, 45); + Polar r = Polar::zero; + + r = -v; + EXPECT_FLOAT_EQ(r.distance, 2); + EXPECT_FLOAT_EQ(r.angle, -135); + EXPECT_TRUE(r == Polar(2, -135)) << "Negate(2 45)"; + + v = Polar(2, -45); + r = -v; + EXPECT_TRUE(r == Polar(2, 135)) << "Negate(2 -45)"; + + v = Polar(2, 0); + r = -v; + EXPECT_TRUE(r == Polar(2, 180)) << "Negate(2 0)"; + + v = Polar(0, 0); + r = -v; + EXPECT_FLOAT_EQ(r.distance, 0.0f); + EXPECT_FLOAT_EQ(r.angle, 0.0f); + EXPECT_TRUE(r == Polar(0, 0)) << "Negate(0 0)"; +} + #endif \ No newline at end of file From 0c54276bd59fd623a98814c7238426462b6b3593 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 15:32:46 +0200 Subject: [PATCH 041/121] equality support --- Angle.cpp | 34 +++++++++++++++++++--------------- Angle.h | 34 ++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 4a039ce..3cb21e3 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -73,12 +73,16 @@ float Angle::SineRuleAngle(float a, float beta, float b) { */ //---------------------- -template <> Angle2 Angle2::pi = 3.1415927410125732421875F; +template <> AngleOf AngleOf::pi = 3.1415927410125732421875F; -template <> Angle2 Angle2::Rad2Deg = 360.0f / (pi * 2); -template <> Angle2 Angle2::Deg2Rad = (pi * 2) / 360.0f; +template <> AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); +template <> AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; -template <> Angle2 Angle2::Normalize(Angle2 angle) { +template <> bool Passer::AngleOf::operator==(AngleOf a) { + return (float)*this == (float)a; +} + +template <> AngleOf AngleOf::Normalize(AngleOf angle) { float angleValue = angle; if (!isfinite(angleValue)) return angleValue; @@ -91,8 +95,8 @@ template <> Angle2 Angle2::Normalize(Angle2 angle) { } template <> -Angle2 Angle2::Clamp(Angle2 angle, Angle2 min, - Angle2 max) { +AngleOf AngleOf::Clamp(AngleOf angle, AngleOf min, + AngleOf max) { float normalizedAngle = Normalize(angle); float r = Float::Clamp(normalizedAngle, min, max); return r; @@ -105,9 +109,9 @@ Angle2 Angle2::Clamp(Angle2 angle, Angle2 min, // } template <> -Angle2 Angle2::MoveTowards(Angle2 fromAngle, - Angle2 toAngle, - Angle2 maxAngle) { +AngleOf AngleOf::MoveTowards(AngleOf fromAngle, + AngleOf toAngle, + AngleOf maxAngle) { float d = toAngle - fromAngle; float sign = signbit(d) ? -1 : 1; d = sign * Float::Clamp(fabs(d), 0, maxAngle); @@ -115,11 +119,11 @@ Angle2 Angle2::MoveTowards(Angle2 fromAngle, } template <> -Angle2 Angle2::CosineRuleSide(float a, float b, - Angle2 gamma) { +AngleOf AngleOf::CosineRuleSide(float a, float b, + AngleOf gamma) { float a2 = a * a; float b2 = b * b; - float d = a2 + b2 - 2 * a * b * cos(gamma * Angle2::Deg2Rad); + float d = a2 + b2 - 2 * a * b * cos(gamma * AngleOf::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) return 0; @@ -129,7 +133,7 @@ Angle2 Angle2::CosineRuleSide(float a, float b, } template <> -Angle2 Angle2::CosineRuleAngle(float a, float b, float c) { +AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { float a2 = a * a; float b2 = b * b; float c2 = c * c; @@ -145,8 +149,8 @@ Angle2 Angle2::CosineRuleAngle(float a, float b, float c) { } template <> -Angle2 Angle2::SineRuleAngle(float a, Angle2 beta, - float b) { +AngleOf AngleOf::SineRuleAngle(float a, AngleOf beta, + float b) { float alpha = asin(a * sin(beta * Angle::Deg2Rad) / b); return alpha; } \ No newline at end of file diff --git a/Angle.h b/Angle.h index 6f130ff..1cb2b8e 100644 --- a/Angle.h +++ b/Angle.h @@ -7,36 +7,38 @@ namespace Passer { -template class Angle2 { +template class AngleOf { public: - Angle2(){}; - Angle2(T v) : value(v) {} + AngleOf(){}; + AngleOf(T v) : value(v) {} operator T() { return value; } - static Angle2 Rad2Deg; - static Angle2 Deg2Rad; + static AngleOf Rad2Deg; + static AngleOf Deg2Rad; - static Angle2 pi; + static AngleOf pi; - static Angle2 Normalize(Angle2 angle); - static Angle2 Clamp(Angle2 angle, Angle2 min, Angle2 max); - static Angle2 Difference(Angle2 a, Angle2 b) { - Angle2 r = Normalize(b - a); + bool AngleOf::operator==(AngleOf a); + + static AngleOf Normalize(AngleOf a); + static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); + static AngleOf Difference(AngleOf a, AngleOf b) { + AngleOf r = Normalize(b - a); return r; }; - static Angle2 MoveTowards(Angle2 fromAngle, Angle2 toAngle, - Angle2 maxAngle); + static AngleOf MoveTowards(AngleOf fromAngle, AngleOf toAngle, + AngleOf maxAngle); - static Angle2 CosineRuleSide(float a, float b, Angle2 gamma); - static Angle2 CosineRuleAngle(float a, float b, float c); + static AngleOf CosineRuleSide(float a, float b, AngleOf gamma); + static AngleOf CosineRuleAngle(float a, float b, float c); - static Angle2 SineRuleAngle(float a, Angle2 beta, float c); + static AngleOf SineRuleAngle(float a, AngleOf beta, float c); private: T value; }; -using Angle = Angle2; +using Angle = AngleOf; /* class Angle { public: From c411b43949312453c00e732a28d3a2d1f4e47425 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 15:33:07 +0200 Subject: [PATCH 042/121] Textual improvement --- Vector2.cpp | 8 ++++---- Vector2.h | 16 +++++++--------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Vector2.cpp b/Vector2.cpp index 5a1495a..6a1a03a 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -53,6 +53,10 @@ const Vector2 Vector2::down = Vector2(0, -1); const Vector2 Vector2::forward = Vector2(0, 1); const Vector2 Vector2::back = Vector2(0, -1); +bool Vector2::operator==(const Vector2 &v) { + return (this->x == v.x && this->y == v.y); +} + float Vector2::Magnitude(const Vector2 &a) { return sqrtf(a.x * a.x + a.y * a.y); } @@ -104,10 +108,6 @@ float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) { return v1.x * v2.x + v1.y * v2.y; } -bool Vector2::operator==(const Vector2 &v) { - return (this->x == v.x && this->y == v.y); -} - float Vector2::Distance(const Vector2 &p1, const Vector2 &p2) { return Magnitude(p1 - p2); } diff --git a/Vector2.h b/Vector2.h index 19daeb1..7fd361c 100644 --- a/Vector2.h +++ b/Vector2.h @@ -98,6 +98,13 @@ public: /// const static Vector2 back; + /// @brief Check if this vector to the given vector + /// @param vector The vector to check against + /// @return true if it is identical to the given vector + /// @note This uses float comparison to check equality which may + /// have strange effects. Equality on floats should be avoided. + bool operator==(const Vector2 &vector); + /// /// The length of a vector /// @@ -189,15 +196,6 @@ public: /// The dot product of the two vectors static float Dot(const Vector2 &vector1, const Vector2 &vector2); - /// - /// Check is this vector is equal to the given vector - /// - /// The vector to check against - /// True if it is identical to the given vector - /// Note this uses float comparison to check equality which - /// may have strange effects. Equality on float should be avoided. - bool operator==(const Vector2 &vector); - /// /// The distance between two vectors /// From 569309730d3bc5e8d911c4d5d0b5e69f086acff2 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 20:23:07 +0200 Subject: [PATCH 043/121] Initial subtractop test --- test/Polar_test.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/Polar_test.cc b/test/Polar_test.cc index bd1a3b4..7ef43ca 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -68,7 +68,7 @@ TEST(Polar, FromSpherical) { EXPECT_FLOAT_EQ(p.angle, 0.0F) << "p.angle FromSpherical(0 0 90)"; } -TEST(Polar, Negate) { +TEST(Polar, Negation) { Polar v = Polar(2, 45); Polar r = Polar::zero; @@ -92,4 +92,17 @@ TEST(Polar, Negate) { EXPECT_TRUE(r == Polar(0, 0)) << "Negate(0 0)"; } +TEST(Polar, Subtraction) { + Polar v1 = Polar(4, 45); + Polar v2 = Polar(1, -90); + Polar r = Polar::zero; + + r = v1 - v2; + // don't know what to expect yet + + v2 = Polar::zero; + r = v1 - v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Subtraction(0 0)"; +} + #endif \ No newline at end of file From e922a017faeac95cba0fb0a7fc0ce2de8bdd0b77 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 20:25:19 +0200 Subject: [PATCH 044/121] fix == operator --- Angle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Angle.h b/Angle.h index 1cb2b8e..0c7db51 100644 --- a/Angle.h +++ b/Angle.h @@ -18,7 +18,7 @@ public: static AngleOf pi; - bool AngleOf::operator==(AngleOf a); + bool operator==(AngleOf a); static AngleOf Normalize(AngleOf a); static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); From 66e47d736fd9129db31a4650bd936b32435fe735 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 21:35:44 +0200 Subject: [PATCH 045/121] Cleanup Vector2 and Polar --- Angle.h | 2 +- Polar.cpp | 2 +- Polar.h | 78 +++++------- Vector2.cpp | 51 ++++---- Vector2.h | 306 ++++++++++++++++++--------------------------- test/Polar_test.cc | 53 ++++++++ 6 files changed, 232 insertions(+), 260 deletions(-) diff --git a/Angle.h b/Angle.h index 0c7db51..31fc88a 100644 --- a/Angle.h +++ b/Angle.h @@ -11,7 +11,7 @@ template class AngleOf { public: AngleOf(){}; AngleOf(T v) : value(v) {} - operator T() { return value; } + operator T() const { return value; } static AngleOf Rad2Deg; static AngleOf Deg2Rad; diff --git a/Polar.cpp b/Polar.cpp index 5332b24..12b09bd 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -90,7 +90,7 @@ Polar Polar::operator/(const float &f) { this->angle); // Polar(this->angle, this->distance / f); } -float Polar::Distance(Polar &v1, Polar &v2) { +float Polar::Distance(const Polar &v1, const Polar &v2) { float d = Angle::CosineRuleSide(v1.distance, v2.distance, (float)v2.angle - (float)v1.angle); return d; diff --git a/Polar.h b/Polar.h index 9fdb50e..e95fd56 100644 --- a/Polar.h +++ b/Polar.h @@ -12,18 +12,11 @@ namespace Passer { struct Vector2; struct Spherical; -/// -/// A polar vector -/// +/// @brief A polar vector /// This will use the polar coordinate system consisting of a angle from a /// reference direction and a distance. struct Polar { public: - /// - /// The distance in meters - /// - /// The distance should never be negative - /// @brief The distance in meters /// @remark The distance shall never be negative float distance; @@ -52,6 +45,11 @@ public: /// @brief A polar vector with zero degrees and distance const static Polar zero; + /// @brief Equality test to another vector + /// @param v The vector to check against + /// @return true: if it is identical to the given vector + /// @note This uses float comparison to check equality which may have strange + /// effects. Equality on floats should be avoided. bool operator==(const Polar &v); /// @brief Negate the vector @@ -62,48 +60,36 @@ public: /// @param v The vector to subtract /// @return The result of the subtraction Polar operator-(Polar &v); - - /// - /// Add another polar vector to this polar vector - /// - /// The vector to add - /// The result of adding the vector + /// @brief Add a polar vector to this vector + /// @param v The vector to add + /// @return The result of the addition Polar operator+(Polar &v); + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + Polar operator*(float f) const; + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled factor + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + Polar operator/(const float &f); - /// - /// Scale the vector uniformly up - /// - /// The scaling factor - /// The scaled vector - /// This operation will scale the distance of the vector. The angle will be - /// unaffected. - Polar operator*(float factor) const; + /// @brief The distance between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The distance between the two vectors + static float Distance(const Polar &v1, const Polar &v2); - /// - /// Scale the vector uniformly down - /// - /// The scaling factor - /// The scaled vector - /// This operation will scale the distance of the vector. The angle will be - /// unaffected. - Polar operator/(const float &factor); - - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vector - /// The distance between the two vectors - static float Distance(Polar &v1, Polar &v2); - - /// - /// Rotate the vector - /// - /// The vector to rotate - /// Angle in radias to rotate - /// The rotated vector - static Polar Rotate(Polar v, Angle angle); + /// @brief Rotate a vector + /// @param v The vector to rotate + /// @param a The angle in degreesto rotate + /// @return The rotated vector + static Polar Rotate(Polar v, Angle a); }; + } // namespace Passer using namespace Passer; diff --git a/Vector2.cpp b/Vector2.cpp index 6a1a03a..0aeaba1 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -17,22 +17,18 @@ Vector2::Vector2() { x = 0; y = 0; } - Vector2::Vector2(float _x, float _y) { x = _x; y = _y; } - Vector2::Vector2(Vec2 v) { x = v.x; y = v.y; } - Vector2::Vector2(Vector3 v) { x = v.x; y = v.z; } - Vector2::Vector2(Polar p) { float horizontalRad = p.angle * Angle::Deg2Rad; float cosHorizontal = cosf(horizontalRad); @@ -61,7 +57,6 @@ float Vector2::Magnitude(const Vector2 &a) { return sqrtf(a.x * a.x + a.y * a.y); } float Vector2::magnitude() const { return (float)sqrtf(x * x + y * y); } - float Vector2::SqrMagnitude(const Vector2 &a) { return a.x * a.x + a.y * a.y; } float Vector2::sqrMagnitude() const { return (x * x + y * y); } @@ -82,12 +77,11 @@ Vector2 Vector2::normalized() const { return result; } +Vector2 Vector2::operator-() { return Vector2(-this->x, -this->y); } + Vector2 Vector2::operator-(const Vector2 &v2) const { return Vector2(this->x - v2.x, this->y - v2.y); } - -Vector2 Vector2::operator-() { return Vector2(-this->x, -this->y); } - Vector2 Vector2::operator+(const Vector2 &v2) const { return Vector2(this->x + v2.x, this->y + v2.y); } @@ -95,30 +89,27 @@ Vector2 Vector2::operator+(const Vector2 &v2) const { Vector2 Vector2::Scale(const Vector2 &p1, const Vector2 &p2) { return Vector2(p1.x * p2.x, p1.y * p2.y); } - -Vector2 Vector2::operator*(float f) const { +Vector2 Vector2::operator*(const float &f) const { return Vector2(this->x * f, this->y * f); } - -Vector2 Vector2::operator/(const float &d) { - return Vector2(this->x / d, this->y / d); +Vector2 Vector2::operator/(const float &f) const { + return Vector2(this->x / f, this->y / f); } float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) { return v1.x * v2.x + v1.y * v2.y; } -float Vector2::Distance(const Vector2 &p1, const Vector2 &p2) { - return Magnitude(p1 - p2); +float Vector2::Distance(const Vector2 &v1, const Vector2 &v2) { + return Magnitude(v1 - v2); } -float Vector2::Angle(Vector2 from, Vector2 to) { - return (float)fabs(SignedAngle(from, to)); +float Vector2::Angle(const Vector2 &v1, const Vector2 &v2) { + return (float)fabs(SignedAngle(v1, v2)); } - -float Vector2::SignedAngle(Vector2 from, Vector2 to) { - float sqrMagFrom = from.sqrMagnitude(); - float sqrMagTo = to.sqrMagnitude(); +float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { + float sqrMagFrom = v1.sqrMagnitude(); + float sqrMagTo = v2.sqrMagnitude(); if (sqrMagFrom == 0 || sqrMagTo == 0) return 0; @@ -129,13 +120,13 @@ float Vector2::SignedAngle(Vector2 from, Vector2 to) { return nanf(""); #endif - float angleFrom = atan2(from.y, from.x); - float angleTo = atan2(to.y, to.x); + float angleFrom = atan2(v1.y, v1.x); + float angleTo = atan2(v2.y, v2.x); return -(angleTo - angleFrom) * Angle::Rad2Deg; } -Vector2 Vector2::Rotate(Vector2 v, float angle) { - float angleRad = angle * Angle::Deg2Rad; +Vector2 Vector2::Rotate(const Vector2 &v, const float &a) { + float angleRad = a * Angle::Deg2Rad; #if defined(AVR) float sinValue = sin(angleRad); float cosValue = cos(angleRad); // * Angle::Deg2Rad); @@ -146,12 +137,12 @@ Vector2 Vector2::Rotate(Vector2 v, float angle) { float tx = v.x; float ty = v.y; - v.x = (cosValue * tx) - (sinValue * ty); - v.y = (sinValue * tx) + (cosValue * ty); - return v; + Vector2 r = Vector2((cosValue * tx) - (sinValue * ty), + (sinValue * tx) + (cosValue * ty)); + return r; } -Vector2 Vector2::Lerp(Vector2 from, Vector2 to, float f) { - Vector2 v = from + (to - from) * f; +Vector2 Vector2::Lerp(const Vector2 &v1, const Vector2 &v2, const float f) { + Vector2 v = v1 + (v2 - v1) * f; return v; } diff --git a/Vector2.h b/Vector2.h index 7fd361c..fbf5d3e 100644 --- a/Vector2.h +++ b/Vector2.h @@ -29,221 +29,163 @@ namespace Passer { struct Vector3; struct Polar; -/// -/// A 2-dimensional vector -/// -/// This uses the right-handed coordinate system. +/// @brief A 2=dimensional vector +/// @remark This uses the right=handed carthesian coordinate system. +/// @note This implementation intentionally avoids the use of x and y struct Vector2 : Vec2 { public: - /// - /// Create a new 2-dimensinal zero vector - /// + /// @brief A new 2-dimensional zero vector Vector2(); - /// - /// Create a new 2-dimensional vector - /// - /// x axis value - /// y axis value - Vector2(float x, float y); - /// - /// Create a vector from C-style Vec2 - /// - /// The C-style Vec + /// @brief A new 2-dimensional vector + /// @param sideward The sideward value + /// @param forward The forward value + Vector2(float sideward, float forward); + /// @brief A vector created from a C-style Vec2 + /// @param v The C-syle Vec2 Vector2(Vec2 v); - - /// - /// Convert a Vector3 to a Vector3 - /// - /// The 3D vector + /// @brief Convert a Vector3 to a Vector2 + /// @param v The 3D vector + /// @note This will project the vector to the horizontal plane Vector2(Vector3 v); + /// @brief Convert a Polar vector to a 2-dimensional vector + /// @param v The vector in polar coordinates + Vector2(Polar v); - Vector2(Polar p); - - /// - /// Vector2 destructor - /// - /// A vector with zero for all axis - /// + /// @brief A vector with zero for all axis const static Vector2 zero; - /// - /// A vector with values (1, 1) - /// + /// @brief A vector with one for all axis const static Vector2 one; - /// - /// A vector with values (1, 0) - /// - /// + /// @brief A normalized right-oriented vector const static Vector2 right; - /// - /// A vector3 with values (-1, 0) - /// + /// @brief A normalized left-oriented vector const static Vector2 left; - /// - /// A vector with values (0, 1) - /// + /// @brief A normalized up-oriented vector + /// @note This is equal to Vector2::forward const static Vector2 up; - /// - /// A vector with values (0, -1) - /// + /// @brief A normalized down-oriented vector + /// @note This is equal to Vector2::down const static Vector2 down; - /// - /// A vector with values (0, 1) - /// + /// @brief A normalized forward-oriented vector + /// @note This is equal to Vector2::up const static Vector2 forward; - /// - /// A vector with values (0, -1) - /// + /// @brief A normalized back-oriented vector + /// @note This is equal to Vector2::down const static Vector2 back; /// @brief Check if this vector to the given vector - /// @param vector The vector to check against + /// @param v The vector to check against /// @return true if it is identical to the given vector - /// @note This uses float comparison to check equality which may - /// have strange effects. Equality on floats should be avoided. - bool operator==(const Vector2 &vector); + /// @note This uses float comparison to check equality which may have strange + /// effects. Equality on floats should be avoided. + bool operator==(const Vector2 &v); - /// - /// The length of a vector - /// - /// The vector for which you need the length - /// The length of the given vector - static float Magnitude(const Vector2 &vector); - /// - /// The length of this vector - /// - /// The length of this vector + /// @brief The vector length + /// @param v The vector for which you need the length + /// @return The vector length + static float Magnitude(const Vector2 &v); + /// @brief The vector length + /// @return The vector length float magnitude() const; - /// - /// The squared length of a vector - /// - /// The vector for which you need the squared - /// length The squatred length The squared length - /// is computationally simpler than the real length. Think of Pythagoras A^2 + - /// B^2 = C^2. This leaves out the calculation of the squared root of C. - static float SqrMagnitude(const Vector2 &vector); - /// - /// The squared length of this vector - /// - /// The squared length - /// The squared length is computationally simpler than the real length. - /// Think of Pythagoras A^2 + B^2 = C^2. - /// This leaves out the calculation of the squared root of C. + /// @brief The squared vector length + /// @param v The vector for which you need the squared length + /// @return The squared vector length + /// @remark The squared length is computationally simpler than the real + /// length. Think of Pythagoras A^2 + B^2 = C^2. This prevents the calculation + /// of the squared root of C. + static float SqrMagnitude(const Vector2 &v); + /// @brief The squared vector length + /// @return The squared vector length + /// @remark The squared length is computationally simpler than the real + /// length. Think of Pythagoras A^2 + B^2 = C^2. This prevents the calculation + /// of the squared root of C. float sqrMagnitude() const; - /// - /// Connvert a vector to a length of 1 - /// - /// The vector to convert - /// The vector with length 1 - static Vector2 Normalize(Vector2 vector); - /// - /// Convert the vector to a length of a - /// - /// The vector with length 1 + + /// @brief Convert the vector to a length of 1 + /// @param v The vector to convert + /// @return The vector normalized to a length of 1 + static Vector2 Normalize(Vector2 v); + /// @brief Convert the vector to a length 1 + /// @return The vector normalized to a length of 1 Vector2 normalized() const; - /// - /// Negate the vector - /// - /// The negated vector - /// This will result in a vector pointing in the opposite direction + /// @brief Negate the vector such that it points in the opposite direction + /// @return The negated vector Vector2 operator-(); - /// - /// Subtract a vector from this vector - /// - /// The vector to subtract from this vector - /// The result of the subtraction - Vector2 operator-(const Vector2 &vector) const; - /// - /// Add another vector to this vector - /// - /// The vector to add - /// The result of adding the vector - Vector2 operator+(const Vector2 &vector2) const; + /// @brief Subtract a vector from this vector + /// @param v The vector to subtract from this vector + /// @return The result of the subtraction + Vector2 operator-(const Vector2 &v) const; + /// @brief Add a vector to this vector + /// @param v The vector to add to this vector + /// @return The result of the addition + Vector2 operator+(const Vector2 &v) const; - /// - /// Scale a vector using another vector - /// - /// The vector to scale - /// A vector with scaling factors - /// The scaled vector - /// Each component of the vector v1 will be multiplied with the - /// component from the scaling vector v2. - static Vector2 Scale(const Vector2 &vector1, const Vector2 &vector2); - /// - /// Scale a vector uniformly up - /// - /// The scaling factor - /// The scaled vector - /// Each component of the vector will be multipled with the same factor. - Vector2 operator*(float factor) const; - /// - /// Scale a vector uniformy down - /// - /// The scaling factor - /// The scaled vector - /// Each componet of the vector will be divided by the same factor. - Vector2 operator/(const float &factor); + /// @brief Scale a vector using another vector + /// @param v1 The vector to scale + /// @param v2 A vector with the scaling factors + /// @return The scaled vector + /// @remark Each component of the vector v1 will be multiplied with the + /// matching component from the scaling vector v2. + static Vector2 Scale(const Vector2 &v1, const Vector2 &v2); + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark Each component of the vector will be multipled with the same + /// factor f. + Vector2 operator*(const float &f) const; + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled vector + /// @remark Each componet of the vector will be divided by the same factor. + Vector2 operator/(const float &f) const; - /// - /// The dot product of two vectors - /// - /// The first vector - /// The second vector - /// The dot product of the two vectors - static float Dot(const Vector2 &vector1, const Vector2 &vector2); + /// @brief The dot product of two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The dot product of the two vectors + static float Dot(const Vector2 &v1, const Vector2 &v2); - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vectors - /// The distance between the two vectors - static float Distance(const Vector2 &vector1, const Vector2 &vector2); + /// @brief The distance between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The distance between the two vectors + static float Distance(const Vector2 &v1, const Vector2 &v2); - /// - /// Calculate the angle between two vectors - /// - /// The first vector - /// The second vector - /// The angle - /// This reterns an unsigned angle which is the shortest distance - /// between the two vectors. Use Vector3::SignedAngle if a - /// signed angle is needed. - static float Angle(Vector2 vector1, Vector2 vector2); + /// @brief The angle between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The angle between the two vectors + /// @remark This reterns an unsigned angle which is the shortest distance + /// between the two vectors. Use Vector2::SignedAngle if a signed angle is + /// needed. + static float Angle(const Vector2 &v1, const Vector2 &v2); + /// @brief The signed angle between two vectors + /// @param v1 The starting vector + /// @param v2 The ending vector + /// @return The signed angle between the two vectors + static float SignedAngle(const Vector2 &v1, const Vector2 &v2); - /// - /// Calculate the angle between two vectors rotation around an axis. - /// - /// The starting vector - /// The ending vector - /// The axis to rotate around - /// The signed angle - static float SignedAngle(Vector2 from, Vector2 to); + /// @brief Rotate the vector + /// @param v The vector to rotate + /// @param a The angle in degrees to rotate + /// @return The rotated vector + static Vector2 Rotate(const Vector2 &v, const float &a); - /// - /// Rotate the vector - /// - /// The vector to rotate - /// Angle in radias to rotate - /// The rotated vector - static Vector2 Rotate(Vector2 v, float angle); - - /// - /// Lerp between two vectors - /// - /// The from vector - /// The to vector - /// The interpolation distance (0..1) - /// The lerped vector - /// The factor f is unclamped. Value 0 matches the *from* vector, Value 1 - /// matches the *to* vector Value -1 is *from* vector minus the difference - /// between *from* and *to* etc. - static Vector2 Lerp(Vector2 from, Vector2 to, float f); + /// @brief Lerp (linear interpolation) between two vectors + /// @param v1 The starting vector + /// @param v2 The end vector + /// @param f The interpolation distance + /// @return The lerped vector + /// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value + /// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference + /// between *v1* and *v2* etc. + static Vector2 Lerp(const Vector2 &v1, const Vector2 &v2, const float f); }; + } // namespace Passer using namespace Passer; diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 7ef43ca..2598e7b 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -105,4 +105,57 @@ TEST(Polar, Subtraction) { EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Subtraction(0 0)"; } +TEST(Polar, Addition) { + Polar v1 = Polar(4, 45); + Polar v2 = Polar(1, -90); + Polar r = Polar::zero; + + r = v1 - v2; + // don't know what to expect yet + + v2 = Polar::zero; + r = v1 + v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; +} + +TEST(Polar, Scale_Multiply) { + Polar v1 = Polar(4, 45); + Polar r = Polar::zero; + + r = v1 * 2.0f; + EXPECT_FLOAT_EQ(r.distance, v1.distance * 2) << "ScaleMult(4 45, 2)"; + EXPECT_FLOAT_EQ(r.angle, v1.angle) << "ScaleMult(4 45, 2)"; +} + +TEST(Polar, Scale_Divide) { + Polar v1 = Polar(4, 45); + Polar r = Polar::zero; + + r = v1 / 2.0f; + EXPECT_FLOAT_EQ(r.distance, v1.distance / 2) << "ScaleDiv(4 45, 2)"; + EXPECT_FLOAT_EQ(r.angle, v1.angle) << "ScaleDiv(4 45, 2)"; +} + +TEST(Polar, Distance) { + Polar v1 = Polar(4, 45); + Polar v2 = Polar(1, -90); + float d = 0; + + d = Polar::Distance(v1, v2); + // don't know what to expect yet + + v2 = Polar::zero; + d = Polar::Distance(v1, v2); + EXPECT_FLOAT_EQ(d, v1.distance) << "Distance(4 45, zero)"; +} + +TEST(Polar, Rotate) { + Polar v = Polar(4, 45); + Polar r = Polar::zero; + + r = Polar::Rotate(v, 45); + EXPECT_FLOAT_EQ(r.distance, v.distance) << "Rotate(4 45, 45)"; + EXPECT_FLOAT_EQ(r.angle, 90.0f) << "Rotate(4 45, 45)"; +} + #endif \ No newline at end of file From f7d9d976fc485f813301a5733a54687f27c099fe Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 12 May 2024 21:56:49 +0200 Subject: [PATCH 046/121] Cleanup --- Polar.cpp | 16 +++++++++++++--- Polar.h | 18 +++++++++++++++++- Vector2.cpp | 10 +++++----- Vector2.h | 12 +++++++----- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index 12b09bd..f170ecd 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -40,6 +40,15 @@ bool Polar::operator==(const Polar &v) { return (this->distance == v.distance && this->angle == v.angle); } +Polar Polar::Normalize(const Polar &v) { + Polar r = Polar(1, v.angle); + return r; +} +Polar Polar::normalized() const { + Polar r = Polar(1, this->angle); + return r; +} + Polar Polar::operator+(Polar &v2) { if (v2.distance == 0) return Polar(this->distance, this->angle); @@ -96,7 +105,8 @@ float Polar::Distance(const Polar &v1, const Polar &v2) { return d; } -Polar Polar::Rotate(Polar v, Angle angle) { - v.angle = Angle::Normalize(v.angle + angle); - return v; +Polar Polar::Rotate(const Polar &v, Angle angle) { + Angle a = Angle::Normalize(v.angle + angle); + Polar r = Polar(v.distance, a); + return r; } \ No newline at end of file diff --git a/Polar.h b/Polar.h index e95fd56..f5ae017 100644 --- a/Polar.h +++ b/Polar.h @@ -52,6 +52,22 @@ public: /// effects. Equality on floats should be avoided. bool operator==(const Polar &v); + /// @brief The vector length + /// @param v The vector for which you need the length + /// @return The vector length; + inline static float Magnitude(const Polar &v) { return v.distance; } + /// @brief The vector length + /// @return The vector length + inline float magnitude() const { return this->distance; } + + /// @brief Convert the vector to a length of 1 + /// @param v The vector to convert + /// @return The vector normalized to a length of 1 + static Polar Normalize(const Polar &v); + /// @brief Convert the vector to a length of a + /// @return The vector normalized to a length of 1 + Polar normalized() const; + /// @brief Negate the vector /// @return The negated vector /// This will rotate the vector by 180 degrees. Distance will stay the same. @@ -87,7 +103,7 @@ public: /// @param v The vector to rotate /// @param a The angle in degreesto rotate /// @return The rotated vector - static Polar Rotate(Polar v, Angle a); + static Polar Rotate(const Polar &v, Angle a); }; } // namespace Passer diff --git a/Vector2.cpp b/Vector2.cpp index 0aeaba1..c5321ea 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -60,7 +60,7 @@ float Vector2::magnitude() const { return (float)sqrtf(x * x + y * y); } float Vector2::SqrMagnitude(const Vector2 &a) { return a.x * a.x + a.y * a.y; } float Vector2::sqrMagnitude() const { return (x * x + y * y); } -Vector2 Vector2::Normalize(Vector2 v) { +Vector2 Vector2::Normalize(const Vector2 &v) { float num = Vector2::Magnitude(v); Vector2 result = Vector2::zero; if (num > Float::epsilon) { @@ -89,10 +89,10 @@ Vector2 Vector2::operator+(const Vector2 &v2) const { Vector2 Vector2::Scale(const Vector2 &p1, const Vector2 &p2) { return Vector2(p1.x * p2.x, p1.y * p2.y); } -Vector2 Vector2::operator*(const float &f) const { +Vector2 Vector2::operator*(float f) const { return Vector2(this->x * f, this->y * f); } -Vector2 Vector2::operator/(const float &f) const { +Vector2 Vector2::operator/(float f) const { return Vector2(this->x / f, this->y / f); } @@ -125,7 +125,7 @@ float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { return -(angleTo - angleFrom) * Angle::Rad2Deg; } -Vector2 Vector2::Rotate(const Vector2 &v, const float &a) { +Vector2 Vector2::Rotate(const Vector2 &v, Passer::Angle a) { float angleRad = a * Angle::Deg2Rad; #if defined(AVR) float sinValue = sin(angleRad); @@ -142,7 +142,7 @@ Vector2 Vector2::Rotate(const Vector2 &v, const float &a) { return r; } -Vector2 Vector2::Lerp(const Vector2 &v1, const Vector2 &v2, const float f) { +Vector2 Vector2::Lerp(const Vector2 &v1, const Vector2 &v2, float f) { Vector2 v = v1 + (v2 - v1) * f; return v; } diff --git a/Vector2.h b/Vector2.h index fbf5d3e..63d3c08 100644 --- a/Vector2.h +++ b/Vector2.h @@ -5,6 +5,8 @@ #ifndef VECTOR2_H #define VECTOR2_H +#include "Angle.h" + extern "C" { /// /// 2-dimensional Vector representation @@ -106,7 +108,7 @@ public: /// @brief Convert the vector to a length of 1 /// @param v The vector to convert /// @return The vector normalized to a length of 1 - static Vector2 Normalize(Vector2 v); + static Vector2 Normalize(const Vector2 &v); /// @brief Convert the vector to a length 1 /// @return The vector normalized to a length of 1 Vector2 normalized() const; @@ -136,12 +138,12 @@ public: /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - Vector2 operator*(const float &f) const; + Vector2 operator*(float f) const; /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - Vector2 operator/(const float &f) const; + Vector2 operator/(float f) const; /// @brief The dot product of two vectors /// @param v1 The first vector @@ -173,7 +175,7 @@ public: /// @param v The vector to rotate /// @param a The angle in degrees to rotate /// @return The rotated vector - static Vector2 Rotate(const Vector2 &v, const float &a); + static Vector2 Rotate(const Vector2 &v, Passer::Angle a); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector @@ -183,7 +185,7 @@ public: /// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value /// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference /// between *v1* and *v2* etc. - static Vector2 Lerp(const Vector2 &v1, const Vector2 &v2, const float f); + static Vector2 Lerp(const Vector2 &v1, const Vector2 &v2, float f); }; } // namespace Passer From 95713c8621244d8b475ca49c6a8f18a0daf1f054 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 13 May 2024 15:32:42 +0200 Subject: [PATCH 047/121] Cleanup, added utility functions --- Angle.h | 16 -- Matrix.cpp | 8 +- Quaternion.cpp | 63 ++++---- Spherical.cpp | 4 +- Vector2.cpp | 68 +++++--- Vector2.h | 35 ++-- Vector3.cpp | 133 ++++++++------- Vector3.h | 360 +++++++++++++++++------------------------ test/Spherical_test.cc | 24 +-- test/Vector2_test.cc | 11 ++ test/Vector3_test.cc | 34 ++-- 11 files changed, 376 insertions(+), 380 deletions(-) diff --git a/Angle.h b/Angle.h index 31fc88a..943be90 100644 --- a/Angle.h +++ b/Angle.h @@ -39,23 +39,7 @@ private: }; using Angle = AngleOf; -/* -class Angle { -public: - const static float Rad2Deg; - const static float Deg2Rad; - static float Normalize(float angle); - static float Clamp(float angle, float min, float max); - static float Difference(float a, float b); - static float MoveTowards(float fromAngle, float toAngle, float maxAngle); - - static float CosineRuleSide(float a, float b, float gamma); - static float CosineRuleAngle(float a, float b, float c); - - static float SineRuleAngle(float a, float beta, float c); -}; -*/ } // namespace Passer using namespace Passer; diff --git a/Matrix.cpp b/Matrix.cpp index 7a67504..b9b2eab 100644 --- a/Matrix.cpp +++ b/Matrix.cpp @@ -15,9 +15,9 @@ template <> MatrixOf::MatrixOf(unsigned int rows, unsigned int cols) { } template <> MatrixOf::MatrixOf(Vector3 v) : MatrixOf(3, 1) { - Set(0, 0, v.x); - Set(1, 0, v.y); - Set(2, 0, v.z); + Set(0, 0, v.Right()); + Set(1, 0, v.Up()); + Set(2, 0, v.Forward()); } template <> @@ -27,7 +27,7 @@ void MatrixOf::Multiply(const MatrixOf *m1, for (unsigned int colIx2 = 0; colIx2 < m2->cols; colIx2++) { unsigned int rDataIx = colIx2 * m2->cols + rowIx1; r->data[rDataIx] = 0.0F; - for (int kIx = 0; kIx < m2->rows; kIx++) { + for (unsigned int kIx = 0; kIx < m2->rows; kIx++) { unsigned int dataIx1 = rowIx1 * m1->cols + kIx; unsigned int dataIx2 = kIx * m2->cols + colIx2; r->data[rDataIx] += m1->data[dataIx1] * m2->data[dataIx2]; diff --git a/Quaternion.cpp b/Quaternion.cpp index 0389ab2..8f76a71 100644 --- a/Quaternion.cpp +++ b/Quaternion.cpp @@ -115,13 +115,21 @@ Vector3 Quaternion::operator*(const Vector3 &p) const { float num10 = this->w * num; float num11 = this->w * num2; float num12 = this->w * num3; - Vector3 result = Vector3::zero; - result.x = - (1 - (num5 + num6)) * p.x + (num7 - num12) * p.y + (num8 + num11) * p.z; - result.y = - (num7 + num12) * p.x + (1 - (num4 + num6)) * p.y + (num9 - num10) * p.z; - result.z = - (num8 - num11) * p.x + (num9 + num10) * p.y + (1 - (num4 + num5)) * p.z; + + float px = p.Right(); + float py = p.Up(); + float pz = p.Forward(); + // Vector3 result = Vector3::zero; + // result.x = + float rx = + (1 - (num5 + num6)) * px + (num7 - num12) * py + (num8 + num11) * pz; + // result.y = + float ry = + (num7 + num12) * px + (1 - (num4 + num6)) * py + (num9 - num10) * pz; + // result.z = + float rz = + (num8 - num11) * px + (num9 + num10) * py + (1 - (num4 + num5)) * pz; + Vector3 result = Vector3(rx, ry, rz); return result; } @@ -142,15 +150,15 @@ Quaternion Quaternion::LookRotation(const Vector3 &forward, const Vector3 &up) { Vector3 nForward = Vector3::Normalize(forward); Vector3 nRight = Vector3::Normalize(Vector3::Cross(up, nForward)); Vector3 nUp = Vector3::Cross(nForward, nRight); - float m00 = nRight.x; - float m01 = nRight.y; - float m02 = nRight.z; - float m10 = nUp.x; - float m11 = nUp.y; - float m12 = nUp.z; - float m20 = nForward.x; - float m21 = nForward.y; - float m22 = nForward.z; + float m00 = nRight.Right(); // x; + float m01 = nRight.Up(); // y; + float m02 = nRight.Forward(); // z; + float m10 = nUp.Right(); // x; + float m11 = nUp.Up(); // y; + float m12 = nUp.Forward(); // z; + float m20 = nForward.Right(); // x; + float m21 = nForward.Up(); // y; + float m22 = nForward.Forward(); // z; float num8 = (m00 + m11) + m22; Quaternion quaternion = Quaternion(); @@ -219,9 +227,9 @@ Quaternion Quaternion::AngleAxis(float angle, const Vector3 &axis) { radians *= 0.5f; Vector3 axis2 = axis * (float)sin(radians); - result.x = axis2.x; - result.y = axis2.y; - result.z = axis2.z; + result.x = axis2.Right(); // x; + result.y = axis2.Up(); // y; + result.z = axis2.Forward(); // z; result.w = (float)cos(radians); return Quaternion::Normalize(result); @@ -293,7 +301,8 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion &a, const Quaternion &b, blendB = t; } Vector3 v = axyz * blendA + b2.xyz() * blendB; - Quaternion result = Quaternion(v.x, v.y, v.z, blendA * a.w + blendB * b2.w); + Quaternion result = + Quaternion(v.Right(), v.Up(), v.Forward(), blendA * a.w + blendB * b2.w); if (result.GetLengthSquared() > 0.0f) return Quaternion::Normalize(result); else @@ -317,9 +326,9 @@ Quaternion Quaternion::Euler(Vector3 euler) { } Quaternion Quaternion::FromEulerRad(Vector3 euler) { - float yaw = euler.x; - float pitch = euler.y; - float roll = euler.z; + float yaw = euler.Right(); + float pitch = euler.Up(); + float roll = euler.Forward(); float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)sin((float)rollOver2); float cosRollOver2 = (float)cos((float)rollOver2); @@ -348,9 +357,9 @@ Quaternion Quaternion::EulerXYZ(Vector3 euler) { return Quaternion::FromEulerRadXYZ(euler * Deg2Rad); } Quaternion Quaternion::FromEulerRadXYZ(Vector3 euler) { - float yaw = euler.x; - float pitch = euler.y; - float roll = euler.z; + float yaw = euler.Right(); // x; + float pitch = euler.Up(); // y; + float roll = euler.Forward(); // z; float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)sin((float)rollOver2); float cosRollOver2 = (float)cos((float)rollOver2); @@ -389,7 +398,7 @@ Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) { Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis Vector3 p = Vector3::Project( ra, axis); // return projection ra on to axis (parallel component) - Quaternion twist = Quaternion(p.x, p.y, p.z, rotation.w); + Quaternion twist = Quaternion(p.Right(), p.Up(), p.Forward(), rotation.w); twist = Quaternion::Normalize(twist); return twist; } diff --git a/Spherical.cpp b/Spherical.cpp index 699d01e..3e623b3 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -37,8 +37,8 @@ Spherical::Spherical(Vector3 v) { this->horizontalAngle = 0.0f; } else { this->verticalAngle = - (90.0f - acosf(v.y / this->distance) * Angle::Rad2Deg); - this->horizontalAngle = atan2f(v.x, v.z) * Angle::Rad2Deg; + (90.0f - acosf(v.Up() / this->distance) * Angle::Rad2Deg); + this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; } } diff --git a/Vector2.cpp b/Vector2.cpp index c5321ea..1ab580a 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -21,13 +21,13 @@ Vector2::Vector2(float _x, float _y) { x = _x; y = _y; } -Vector2::Vector2(Vec2 v) { - x = v.x; - y = v.y; -} +// Vector2::Vector2(Vec2 v) { +// x = v.x; +// y = v.y; +// } Vector2::Vector2(Vector3 v) { - x = v.x; - y = v.z; + x = v.Right(); // x; + y = v.Forward(); // z; } Vector2::Vector2(Polar p) { float horizontalRad = p.angle * Angle::Deg2Rad; @@ -53,11 +53,11 @@ bool Vector2::operator==(const Vector2 &v) { return (this->x == v.x && this->y == v.y); } -float Vector2::Magnitude(const Vector2 &a) { - return sqrtf(a.x * a.x + a.y * a.y); +float Vector2::Magnitude(const Vector2 &v) { + return sqrtf(v.x * v.x + v.y * v.y); } float Vector2::magnitude() const { return (float)sqrtf(x * x + y * y); } -float Vector2::SqrMagnitude(const Vector2 &a) { return a.x * a.x + a.y * a.y; } +float Vector2::SqrMagnitude(const Vector2 &v) { return v.x * v.x + v.y * v.y; } float Vector2::sqrMagnitude() const { return (x * x + y * y); } Vector2 Vector2::Normalize(const Vector2 &v) { @@ -79,21 +79,47 @@ Vector2 Vector2::normalized() const { Vector2 Vector2::operator-() { return Vector2(-this->x, -this->y); } -Vector2 Vector2::operator-(const Vector2 &v2) const { - return Vector2(this->x - v2.x, this->y - v2.y); +Vector2 Vector2::operator-(const Vector2 &v) const { + return Vector2(this->x - v.x, this->y - v.y); } -Vector2 Vector2::operator+(const Vector2 &v2) const { - return Vector2(this->x + v2.x, this->y + v2.y); +Vector2 Vector2::operator-=(const Vector2 &v) { + this->x -= v.x; + this->y -= v.y; + return *this; +} +Vector2 Vector2::operator+(const Vector2 &v) const { + return Vector2(this->x + v.x, this->y + v.y); +} +Vector2 Vector2::operator+=(const Vector2 &v) { + this->x += v.x; + this->y += v.y; + return *this; } -Vector2 Vector2::Scale(const Vector2 &p1, const Vector2 &p2) { - return Vector2(p1.x * p2.x, p1.y * p2.y); +Vector2 Vector2::Scale(const Vector2 &v1, const Vector2 &v2) { + return Vector2(v1.x * v2.x, v1.y * v2.y); } -Vector2 Vector2::operator*(float f) const { - return Vector2(this->x * f, this->y * f); +Vector2 Passer::operator*(const Vector2 &v, const float f) { + return Vector2(v.x * f, v.y * f); } -Vector2 Vector2::operator/(float f) const { - return Vector2(this->x / f, this->y / f); +Vector2 Passer::operator*(const float f, const Vector2 &v) { + return Vector2(v.x * f, v.y * f); +} +Vector2 Vector2::operator*=(const float f) { + this->x *= f; + this->y *= f; + return *this; +} +Vector2 Passer::operator/(const Vector2 &v, const float f) { + return Vector2(v.x / f, v.y / f); +} +Vector2 Passer::operator/(const float f, const Vector2 &v) { + return Vector2(v.x / f, v.y / f); +} +Vector2 Vector2::operator/=(const float f) { + this->x /= f; + this->y /= f; + return *this; } float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) { @@ -120,8 +146,8 @@ float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { return nanf(""); #endif - float angleFrom = atan2(v1.y, v1.x); - float angleTo = atan2(v2.y, v2.x); + float angleFrom = atan2f(v1.y, v1.x); + float angleTo = atan2f(v2.y, v2.x); return -(angleTo - angleFrom) * Angle::Rad2Deg; } diff --git a/Vector2.h b/Vector2.h index 63d3c08..055375a 100644 --- a/Vector2.h +++ b/Vector2.h @@ -35,16 +35,15 @@ struct Polar; /// @remark This uses the right=handed carthesian coordinate system. /// @note This implementation intentionally avoids the use of x and y struct Vector2 : Vec2 { + friend struct Vec2; + public: /// @brief A new 2-dimensional zero vector Vector2(); /// @brief A new 2-dimensional vector - /// @param sideward The sideward value - /// @param forward The forward value - Vector2(float sideward, float forward); - /// @brief A vector created from a C-style Vec2 - /// @param v The C-syle Vec2 - Vector2(Vec2 v); + /// @param right The distance in the right direction in meters + /// @param forward The distance in the forward direction in meters + Vector2(float right, float forward); /// @brief Convert a Vector3 to a Vector2 /// @param v The 3D vector /// @note This will project the vector to the horizontal plane @@ -64,18 +63,18 @@ public: const static Vector2 right; /// @brief A normalized left-oriented vector const static Vector2 left; - /// @brief A normalized up-oriented vector - /// @note This is equal to Vector2::forward - const static Vector2 up; - /// @brief A normalized down-oriented vector - /// @note This is equal to Vector2::down - const static Vector2 down; /// @brief A normalized forward-oriented vector /// @note This is equal to Vector2::up const static Vector2 forward; /// @brief A normalized back-oriented vector /// @note This is equal to Vector2::down const static Vector2 back; + /// @brief A normalized up-oriented vector + /// @note This is a convenience function which is equal to Vector2::forward + const static Vector2 up; + /// @brief A normalized down-oriented vector + /// @note This is a convenience function which is equal to Vector2::down + const static Vector2 down; /// @brief Check if this vector to the given vector /// @param v The vector to check against @@ -121,12 +120,14 @@ public: /// @param v The vector to subtract from this vector /// @return The result of the subtraction Vector2 operator-(const Vector2 &v) const; + Vector2 operator-=(const Vector2 &v); /// @brief Add a vector to this vector /// @param v The vector to add to this vector /// @return The result of the addition Vector2 operator+(const Vector2 &v) const; + Vector2 operator+=(const Vector2 &v); - /// @brief Scale a vector using another vector + /// @brief Scale the vector using another vector /// @param v1 The vector to scale /// @param v2 A vector with the scaling factors /// @return The scaled vector @@ -138,12 +139,16 @@ public: /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - Vector2 operator*(float f) const; + friend Vector2 operator*(const Vector2 &v, const float f); + friend Vector2 operator*(const float f, const Vector2 &v); + Vector2 operator*=(const float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - Vector2 operator/(float f) const; + friend Vector2 operator/(const Vector2 &v, const float f); + friend Vector2 operator/(const float f, const Vector2 &v); + Vector2 operator/=(const float f); /// @brief The dot product of two vectors /// @param v1 The first vector diff --git a/Vector3.cpp b/Vector3.cpp index 3ee597e..2cf43f1 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -13,21 +13,21 @@ const float Rad2Deg = 57.29578F; const float epsilon = 1E-05f; Vector3::Vector3() { - x = 0; - y = 0; - z = 0; + this->x = 0; + this->y = 0; + this->z = 0; } -Vector3::Vector3(float _x, float _y, float _z) { - x = _x; - y = _y; - z = _z; +Vector3::Vector3(float right, float up, float forward) { + this->x = right; + this->y = up; + this->z = forward; } -Vector3::Vector3(Vec3 v) { - x = v.x; - y = v.y; - z = v.z; +Vector3::Vector3(Vector2 v) { + this->x = v.x; + this->y = 0.0f; + this->z = v.y; } Vector3::Vector3(Spherical s) { @@ -61,17 +61,17 @@ const Vector3 Vector3::back = Vector3(0, 0, -1); // inline float Vector3::Forward() { return z; } // inline float Vector3::Up() { return y; } // inline float Vector3::Right() { return x; } -Vector3 Vector3::FromHorizontal(const Vector2 &v) { - return Vector3(v.x, 0, v.y); -} +// Vector3 Vector3::FromHorizontal(const Vector2 &v) { +// return Vector3(v.x, 0, v.y); +// } -float Vector3::Magnitude(const Vector3 &a) { - return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z); +float Vector3::Magnitude(const Vector3 &v) { + return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); } float Vector3::magnitude() const { return (float)sqrtf(x * x + y * y + z * z); } -float Vector3::SqrMagnitude(const Vector3 &a) { - return a.x * a.x + a.y * a.y + a.z * a.z; +float Vector3::SqrMagnitude(const Vector3 &v) { + return v.x * v.x + v.y * v.y + v.z * v.z; } float Vector3::sqrMagnitude() const { return (x * x + y * y + z * z); } @@ -92,26 +92,55 @@ Vector3 Vector3::normalized() const { return result; } -Vector3 Vector3::operator-(const Vector3 &v2) const { - return Vector3(this->x - v2.x, this->y - v2.y, this->z - v2.z); +Vector3 Vector3::operator-() const { + return Vector3(-this->x, -this->y, -this->z); } -Vector3 Vector3::operator-() { return Vector3(-this->x, -this->y, -this->z); } - -Vector3 Vector3::operator+(const Vector3 &v2) const { - return Vector3(this->x + v2.x, this->y + v2.y, this->z + v2.z); +Vector3 Vector3::operator-(const Vector3 &v) const { + return Vector3(this->x - v.x, this->y - v.y, this->z - v.z); +} +Vector3 Vector3::operator-=(const Vector3 &v) { + this->x -= v.x; + this->y -= v.y; + this->z -= v.z; + return *this; +} +Vector3 Vector3::operator+(const Vector3 &v) const { + return Vector3(this->x + v.x, this->y + v.y, this->z + v.z); +} +Vector3 Vector3::operator+=(const Vector3 &v) { + this->x += v.x; + this->y += v.y; + this->z += v.z; + return *this; } -Vector3 Vector3::Scale(const Vector3 &p1, const Vector3 &p2) { - return Vector3(p1.x * p2.x, p1.y * p2.y, p1.z * p2.z); +Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) { + return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } - -Vector3 Vector3::operator*(float f) const { - return Vector3(this->x * f, this->y * f, this->z * f); +Vector3 Passer::operator*(const Vector3 &v, const float f) { + return Vector3(v.x * f, v.y * f, v.z * f); } - -Vector3 Vector3::operator/(float d) const { - return Vector3(this->x / d, this->y / d, this->z / d); +Vector3 Passer::operator*(const float f, const Vector3 &v) { + return Vector3(v.x * f, v.y * f, v.z * f); +} +Vector3 Vector3::operator*=(const float f) { + this->x *= f; + this->y *= f; + this->z *= f; + return *this; +} +Vector3 Passer::operator/(const Vector3 &v, const float f) { + return Vector3(v.x / f, v.y / f, v.z / f); +} +Vector3 Passer::operator/(const float f, const Vector3 &v) { + return Vector3(v.x / f, v.y / f, v.z / f); +} +Vector3 Vector3::operator/=(const float f) { + this->x /= f; + this->y /= f; + this->z /= f; + return *this; } float Vector3::Dot(const Vector3 &v1, const Vector3 &v2) { @@ -122,8 +151,8 @@ bool Vector3::operator==(const Vector3 &v) { return (this->x == v.x && this->y == v.y && this->z == v.z); } -float Vector3::Distance(const Vector3 &p1, const Vector3 &p2) { - return Magnitude(p1 - p2); +float Vector3::Distance(const Vector3 &v1, const Vector3 &v2) { + return Magnitude(v1 - v2); } Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) { @@ -131,25 +160,19 @@ Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) { v1.x * v2.y - v1.y * v2.x); } -Vector3 Vector3::Project(const Vector3 &vector, const Vector3 &onNormal) { - float sqrMagnitude = Dot(onNormal, onNormal); +Vector3 Vector3::Project(const Vector3 &v, const Vector3 &n) { + float sqrMagnitude = Dot(n, n); if (sqrMagnitude < epsilon) return Vector3::zero; else { - float dot = Dot(vector, onNormal); - Vector3 r = onNormal * dot / sqrMagnitude; + float dot = Dot(v, n); + Vector3 r = n * dot / sqrMagnitude; return r; } } -Vector3 Vector3::ProjectOnPlane(const Vector3 &vector, - const Vector3 &planeNormal) { - Vector3 r = vector - Project(vector, planeNormal); - return r; -} - -Vector2 Vector3::ProjectHorizontalPlane(const Vector3 &vector) { - Vector2 r = Vector2(vector.x, vector.z); +Vector3 Vector3::ProjectOnPlane(const Vector3 &v, const Vector3 &n) { + Vector3 r = v - Project(v, n); return r; } @@ -159,12 +182,12 @@ float clamp(float x, float lower, float upper) { return upperClamp; } -float Vector3::Angle(const Vector3 &from, const Vector3 &to) { - float denominator = sqrtf(from.sqrMagnitude() * to.sqrMagnitude()); +float Vector3::Angle(const Vector3 &v1, const Vector3 &v2) { + float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude()); if (denominator < epsilon) return 0; - float dot = Vector3::Dot(from, to); + float dot = Vector3::Dot(v1, v2); float fraction = dot / denominator; if (isnan(fraction)) return fraction; // short cut to returning NaN universally @@ -174,12 +197,12 @@ float Vector3::Angle(const Vector3 &from, const Vector3 &to) { return r; } -float Vector3::SignedAngle(const Vector3 &from, const Vector3 &to, +float Vector3::SignedAngle(const Vector3 &v1, const Vector3 &v2, const Vector3 &axis) { // angle in [0,180] - float angle = Vector3::Angle(from, to); + float angle = Vector3::Angle(v1, v2); - Vector3 cross = Vector3::Cross(from, to); + Vector3 cross = Vector3::Cross(v1, v2); float b = Vector3::Dot(axis, cross); float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F); @@ -189,7 +212,7 @@ float Vector3::SignedAngle(const Vector3 &from, const Vector3 &to, return signed_angle; } -Vector3 Vector3::Lerp(const Vector3 &from, const Vector3 &to, float f) { - Vector3 v = from + (to - from) * f; +Vector3 Vector3::Lerp(const Vector3 &v1, const Vector3 &v2, float f) { + Vector3 v = v1 + (v2 - v1) * f; return v; -} \ No newline at end of file +} diff --git a/Vector3.h b/Vector3.h index fbc51e3..5c10bb6 100644 --- a/Vector3.h +++ b/Vector3.h @@ -18,6 +18,7 @@ extern "C" { /// This is a C-style implementation /// This uses the right-handed coordinate system. typedef struct Vec3 { +protected: /// /// The right axis of the vector /// @@ -34,247 +35,184 @@ typedef struct Vec3 { } Vec3; } -/// -/// A 3-dimensional vector -/// -/// This uses the right-handed coordinate system. +/// @brief A 3-dimensional vector +/// @remark This uses a right-handed carthesian coordinate system. +/// @note This implementation intentionally avoids the use of x, y and z values. struct Vector3 : Vec3 { + friend struct Vec3; + public: - /// - /// Create a new 3-dimensinal zero vector - /// + /// @brief A new 3-dimensional zero vector Vector3(); - /// - /// Create a new 3-dimensional vector - /// - /// x axis value - /// y axis value - /// z axis value - Vector3(float x, float y, float z); - /// - /// Create a vector from C-style Vec3 - /// - /// The C-style Vec - Vector3(Vec3 v); - /// - /// Vector3 destructor - /// - Vector3(Spherical s); + /// @brief A new 3-dimensional vector + /// @param right The distance in the right direction in meters + /// @param up The distance in the upward direction in meters + /// @param forward The distance in the forward direction in meters + Vector3(float right, float up, float forward); + /// @brief Convert a 2-dimenstional vector to a 3-dimensional vector + /// @param v The vector to convert + Vector3(Vector2 v); + /// @brief Convert vector in spherical coordinates to 3d carthesian + /// coordinates + /// @param v The vector to convert + Vector3(Spherical v); + + /// @brief Vector3 destructor ~Vector3(); - /// - /// A vector with zero for all axis - /// + /// @brief A vector with zero for all axis const static Vector3 zero; - /// - /// A vector with one for all axis - /// + /// @brief A vector with one for all axis const static Vector3 one; - /// - /// A normalized vector pointing in the right direction - /// + /// @brief A normalized right-oriented vector const static Vector3 right; - /// - /// A normalized vector pointing in the left direction - /// + /// @brief A normalized left-oriented vector const static Vector3 left; - /// - /// A normalized vector pointing in the upward direction - /// + /// @brief A normalized up-oriented vector const static Vector3 up; - /// - /// A normalized vector pointing in the downward direcion - /// + /// @brief A normalized down-oriented vector const static Vector3 down; - /// - /// A normalized vector pointing in the forward direction - /// + /// @brief A normalized forward-oriented vector const static Vector3 forward; - /// - /// A normalized vector pointing in the backward direction - /// + /// @brief A normalized back-oriented vector const static Vector3 back; - // Experimental Access functions which are intended to replace the use of XYZ - inline float Forward() { return z; }; - inline float Up() { return y; }; - inline float Right() { return x; }; - static Vector3 FromHorizontal(const Vector2 &vector); + // Access functions which are intended to replace the use of XYZ + inline float Forward() const { return z; }; + inline float Up() const { return y; }; + inline float Right() const { return x; }; - /// - /// The length of a vector - /// - /// The vector for which you need the length - /// The length of the given vector - static float Magnitude(const Vector3 &vector); - /// - /// The length of this vector - /// - /// The length of this vector + /// @brief Check if this vector to the given vector + /// @param v The vector to check against + /// @return true if it is identical to the given vector + /// @note This uses float comparison to check equality which may have strange + /// effects. Equality on floats should be avoided. + bool operator==(const Vector3 &v); + + /// @brief The vector length + /// @param v The vector for which you need the length + /// @return The vector length + static float Magnitude(const Vector3 &v); + /// @brief The vector length + /// @return The vector length float magnitude() const; - /// - /// The squared length of a vector - /// - /// The vector for which you need the squared - /// length The squatred length The squared length - /// is computationally simpler than the real length. Think of Pythagoras A^2 + - /// B^2 = C^2. This leaves out the calculation of the squared root of C. - static float SqrMagnitude(const Vector3 &vector); - /// - /// The squared length of this vector - /// - /// The squared length - /// The squared length is computationally simpler than the real length. - /// Think of Pythagoras A^2 + B^2 = C^2. - /// This leaves out the calculation of the squared root of C. + /// @brief The squared vector length + /// @param v The vector for which you need the length + /// @return The squared vector length + /// @remark The squared length is computationally simpler than the real + /// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the + /// calculation of the squared root of C. + static float SqrMagnitude(const Vector3 &v); + /// @brief The squared vector length + /// @return The squared vector length + /// @remark The squared length is computationally simpler than the real + /// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the + /// calculation of the squared root of C. float sqrMagnitude() const; - /// - /// Connvert a vector to a length of 1 - /// - /// The vector to convert - /// The vector with length 1 - static Vector3 Normalize(const Vector3 &vector); - /// - /// Convert the vector to a length of a - /// - /// The vector with length 1 + + /// @brief Convert the vector to a length of 1 + /// @param v The vector to convert + /// @return The vector normalized to a length of 1 + static Vector3 Normalize(const Vector3 &v); + /// @brief Convert the vector to a length of 1 + /// @return The vector normalized to a length of 1 Vector3 normalized() const; - /// - /// Negate the vector - /// - /// The negated vector - /// This will result in a vector pointing in the opposite direction - Vector3 operator-(); - /// - /// Subtract a vector from this vector - /// - /// The vector to subtract from this vector - /// The result of the subtraction - Vector3 operator-(const Vector3 &vector) const; + /// @brief Negate te vector such that it points in the opposite direction + /// @return The negated vector + Vector3 operator-() const; - /// - /// Add another vector to this vector - /// - /// The vector to add - /// The result of adding the vector - Vector3 operator+(const Vector3 &vector2) const; + /// @brief Subtract a vector from this vector + /// @param v The vector to subtract from this vector + /// @return The result of this subtraction + Vector3 operator-(const Vector3 &v) const; + Vector3 operator-=(const Vector3 &v); + /// @brief Add a vector to this vector + /// @param v The vector to add to this vector + /// @return The result of the addition + Vector3 operator+(const Vector3 &v) const; + Vector3 operator+=(const Vector3 &v); - /// - /// Scale a vector using another vector - /// - /// The vector to scale - /// A vector with scaling factors - /// The scaled vector - /// Each component of the vector v1 will be multiplied with the - /// component from the scaling vector v2. - static Vector3 Scale(const Vector3 &vector1, const Vector3 &vector2); - /// - /// Scale a vector uniformly up - /// - /// The scaling factor - /// The scaled vector - /// Each component of the vector will be multipled with the same factor. - Vector3 operator*(const float factor) const; - /// - /// Scale a vector uniformy down - /// - /// The scaling factor - /// The scaled vector - /// Each componet of the vector will be divided by the same factor. - Vector3 operator/(const float factor) const; + /// @brief Scale the vector using another vector + /// @param v1 The vector to scale + /// @param v2 A vector with the scaling factors + /// @return The scaled vector + /// @remark Each component of the vector v1 will be multiplied with the + /// matching component from the scaling vector v2. + static Vector3 Scale(const Vector3 &v1, const Vector3 &v2); + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark Each component of the vector will be multipled with the same + /// factor f. + friend Vector3 operator*(const Vector3 &v, const float f); + friend Vector3 operator*(const float f, const Vector3 &v); + Vector3 operator*=(const float f); + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled vector + /// @remark Each componet of the vector will be divided by the same factor. + friend Vector3 operator/(const Vector3 &v, const float f); + friend Vector3 operator/(const float f, const Vector3 &v); + Vector3 operator/=(const float f); - /// - /// The dot product of two vectors - /// - /// The first vector - /// The second vector - /// The dot product of the two vectors - static float Dot(const Vector3 &vector1, const Vector3 &vector2); + /// @brief The distance between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The distance between the two vectors + static float Distance(const Vector3 &v1, const Vector3 &v2); - /// - /// Check is this vector is equal to the given vector - /// - /// The vector to check against - /// True if it is identical to the given vector - /// Note this uses float comparison to check equality which - /// may have strange effects. Equality on float should be avoided. - bool operator==(const Vector3 &vector); + /// @brief The dot product of two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The dot product of the two vectors + static float Dot(const Vector3 &v1, const Vector3 &v2); - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vectors - /// The distance between the two vectors - static float Distance(const Vector3 &vector1, const Vector3 &vector2); + /// @brief The cross product of two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The cross product of the two vectors + static Vector3 Cross(const Vector3 &v1, const Vector3 &v2); - /// - /// The cross product of two vectors - /// - /// The first vector - /// The second vector - /// The cross product of the two vectors - static Vector3 Cross(const Vector3 &vector1, const Vector3 &vector2); - - /// - /// Project a vector on another vector - /// - /// The vector to project - /// The normal vector to project on - /// The projected vector - static Vector3 Project(const Vector3 &vector, const Vector3 &onNormal); - /// - /// Projects a vector onto a plane defined by a normal orthogonal to the + /// @brief Project the vector on another vector + /// @param v The vector to project + /// @param n The normal vecto to project on + /// @return The projected vector + static Vector3 Project(const Vector3 &v, const Vector3 &n); + /// @brief Project the vector on a plane defined by a normal orthogonal to the /// plane. - /// - /// The vector to project - /// The normal of the plane to project on - /// - static Vector3 ProjectOnPlane(const Vector3 &vector, - const Vector3 &planeNormal); + /// @param v The vector to project + /// @param n The normal of the plane to project on + /// @return Teh projected vector + static Vector3 ProjectOnPlane(const Vector3 &v, const Vector3 &n); - /// - /// Projects a vector onto the horizontal plane. - /// - /// The vector to project - /// A 2D carthesian vector with the coordinates in the horizontal - /// plane. - static Vector2 ProjectHorizontalPlane(const Vector3 &vector); - - /// - /// Calculate the angle between two vectors - /// - /// The first vector - /// The second vector - /// - /// This reterns an unsigned angle which is the shortest distance - /// between the two vectors. Use Vector3::SignedAngle if a - /// signed angle is needed. - static float Angle(const Vector3 &vector1, const Vector3 &vector2); - - /// - /// Calculate the angle between two vectors rotation around an axis. - /// - /// The starting vector - /// The ending vector - /// The axis to rotate around - /// The signed angle - static float SignedAngle(const Vector3 &from, const Vector3 &to, + /// @brief The angle between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The angle between the two vectors + /// @remark This reterns an unsigned angle which is the shortest distance + /// between the two vectors. Use Vector3::SignedAngle if a signed angle is + /// needed. + static float Angle(const Vector3 &v1, const Vector3 &v2); + /// @brief The signed angle between two vectors + /// @param v1 The starting vector + /// @param v2 The ending vector + /// @param axis The axis to rotate around + /// @return The signed angle between the two vectors + static float SignedAngle(const Vector3 &v1, const Vector3 &v2, const Vector3 &axis); - /// - /// Lerp between two vectors - /// - /// The from vector - /// The to vector - /// The interpolation distance (0..1) - /// The lerped vector - /// The factor f is unclamped. Value 0 matches the *from* vector, Value 1 - /// matches the *to* vector Value -1 is *from* vector minus the difference - /// between *from* and *to* etc. - static Vector3 Lerp(const Vector3 &from, const Vector3 &to, float f); + /// @brief Lerp (linear interpolation) between two vectors + /// @param v1 The starting vector + /// @param v2 The ending vector + /// @param f The interpolation distance + /// @return The lerped vector + /// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value + /// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference + /// between *v1* and *v2* etc. + static Vector3 Lerp(const Vector3 &v1, const Vector3 &v2, float f); }; + } // namespace Passer using namespace Passer; diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 2740804..df8f18a 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -77,9 +77,9 @@ TEST(Spherical, Incident1) { EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-02); Vector3 r = Vector3(sr); - EXPECT_NEAR(r.x, v.x, 1.0e-02) << "toVector3.x 1 0 0"; - EXPECT_NEAR(r.y, v.y, 1.0e-02) << "toVector3.y 1 0 0"; - EXPECT_NEAR(r.z, v.z, 1.0e-02) << "toVector3.z 1 0 0"; + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0"; } TEST(Spherical, Incident2) { @@ -92,9 +92,9 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); Vector3 r = Vector3(sr); - EXPECT_NEAR(r.x, v.x, 1.0e-06); - EXPECT_NEAR(r.y, v.y, 1.0e-06); - EXPECT_NEAR(r.z, v.z, 1.0e-06); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(0.0f, 1.0f, 1.0f); s = Spherical(v); @@ -105,9 +105,9 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); r = Vector3(sr); - EXPECT_NEAR(r.x, v.x, 1.0e-06); - EXPECT_NEAR(r.y, v.y, 1.0e-06); - EXPECT_NEAR(r.z, v.z, 1.0e-06); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); s = Spherical(v); @@ -117,9 +117,9 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-02); - EXPECT_NEAR(r.x, v.x, 1.0e-06); - EXPECT_NEAR(r.y, v.y, 1.0e-06); - EXPECT_NEAR(r.z, v.z, 1.0e-06); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); // s = Spherical(10, 45, 45); // r = s.ToVector3(); diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index f08c252..ba61ec6 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -168,11 +168,17 @@ TEST(Vector2, Subtract) { v2 = Vector2(4, 5); v = v1 - v2; EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 - 4 5"; + v = v1; + v -= v2; + EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 - 4 5"; v2 = Vector2(0, 0); v = v1 - v2; EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0"; + v -= v2; + EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0"; + if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); v = v1 - v2; @@ -197,10 +203,15 @@ TEST(Vector2, Addition) { v2 = Vector2(-1, -2); v = v1 + v2; EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 + -1 -2"; + v = v1; + v += v2; + EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 + -1 -2"; v2 = Vector2(0, 0); v = v1 + v2; EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0"; + v += v2; + EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0"; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index 483cbdb..4e5003c 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -12,25 +12,25 @@ TEST(Vector3, FromSpherical) { Spherical s = Spherical(v); Vector3 r = Vector3(s); - EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 0 1"; - EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; - EXPECT_FLOAT_EQ(r.z, 1.0F) << "toVector3.z 0 0 1"; + EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 0 1"; + EXPECT_NEAR(r.Up(), 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; + EXPECT_FLOAT_EQ(r.Forward(), 1.0F) << "toVector3.z 0 0 1"; v = Vector3(0, 1, 0); s = Spherical(v); r = Vector3(s); - EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 1 0"; - EXPECT_FLOAT_EQ(r.y, 1.0F) << "toVector3.y 0 1 0"; - EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; + EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 1 0"; + EXPECT_FLOAT_EQ(r.Up(), 1.0F) << "toVector3.y 0 1 0"; + EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; v = Vector3(1, 0, 0); s = Spherical(v); r = Vector3(s); - EXPECT_FLOAT_EQ(r.x, 1.0F) << "toVector3.x 1 0 0"; - EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; - EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; + EXPECT_FLOAT_EQ(r.Right(), 1.0F) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.Up(), 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; } TEST(Vector3, Magnitude) { @@ -118,12 +118,12 @@ TEST(Vector3, Normalize) { if (std::numeric_limits::is_iec559) { v1 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = v1.normalized(); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "v.normalized INFINITY INFINITY INFINITY"; v1 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = v1.normalized(); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "v.normalized -INFINITY -INFINITY -INFINITY"; } } @@ -409,12 +409,12 @@ TEST(Vector3, Cross) { if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::Cross(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Cross(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = Vector3::Cross(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Cross(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -442,12 +442,12 @@ TEST(Vector3, Project) { if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::Project(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Project(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = Vector3::Project(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Project(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -475,12 +475,12 @@ TEST(Vector3, ProjectOnPlane) { if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::ProjectOnPlane(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = Vector3::ProjectOnPlane(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } From 62d74396e10d046d72997229be9c6bca19d1311d Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 13 May 2024 19:01:21 +0200 Subject: [PATCH 048/121] Extend ulitity functions --- Polar.cpp | 76 ++++++++++++++++++++++++++++------------------ Polar.h | 33 ++++++++++++++------ Spherical.cpp | 61 +++++++++++++++++++++++++++++++++++-- Spherical.h | 68 +++++++++++++++++++++++++++++++++++++---- Vector2.cpp | 12 ++++---- Vector2.h | 22 ++++++-------- Vector3.cpp | 12 ++++---- Vector3.h | 20 ++++++------ test/Polar_test.cc | 4 +++ 9 files changed, 227 insertions(+), 81 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index f170ecd..1099a17 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -8,7 +8,6 @@ Polar::Polar() { this->distance = 0.0f; this->angle = 0.0f; } - Polar::Polar(float distance, Angle angle) { // distance should always be 0 or greater if (distance < 0.0f) { @@ -23,20 +22,22 @@ Polar::Polar(float distance, Angle angle) { this->angle = Angle::Normalize(angle); } } - Polar::Polar(Vector2 v) { this->distance = v.magnitude(); this->angle = Vector2::SignedAngle(Vector2::forward, v); } - Polar::Polar(Spherical v) { this->distance = v.distance * cosf(v.verticalAngle * Angle::Deg2Rad); this->angle = v.horizontalAngle; } const Polar Polar::zero = Polar(0.0f, 0.0f); +const Polar Polar::forward = Polar(1.0f, 0.0f); +const Polar Polar::back = Polar(1.0, 180.0f); +const Polar Polar::right = Polar(1.0, 90.0f); +const Polar Polar::left = Polar(1.0, -90.0f); -bool Polar::operator==(const Polar &v) { +bool Polar::operator==(const Polar &v) const { return (this->distance == v.distance && this->angle == v.angle); } @@ -49,26 +50,38 @@ Polar Polar::normalized() const { return r; } -Polar Polar::operator+(Polar &v2) { - if (v2.distance == 0) +Polar Polar::operator-() const { + Polar v = Polar(this->distance, this->angle + 180); + return v; +} + +Polar Polar::operator-(const Polar &v) const { + Polar r = -v; + return *this + r; +} +Polar Polar::operator-=(const Polar &v) { + *this = *this - v; + return *this; +} +Polar Polar::operator+(const Polar &v) const { + if (v.distance == 0) return Polar(this->distance, this->angle); if (this->distance == 0.0f) - return v2; + return v; - float deltaAngle = Angle::Normalize(v2.angle - (float)this->angle); + float deltaAngle = Angle::Normalize(v.angle - (float)this->angle); float rotation = deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle; - if (rotation == 180.0f && v2.distance > 0.0f) { + if (rotation == 180.0f && v.distance > 0.0f) { // angle is too small, take this angle and add the distances - return Polar(this->distance + v2.distance, this->angle); + return Polar(this->distance + v.distance, this->angle); } float newDistance = - Angle::CosineRuleSide(v2.distance, this->distance, rotation); + Angle::CosineRuleSide(v.distance, this->distance, rotation); - float angle = - Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); + float angle = Angle::CosineRuleAngle(newDistance, this->distance, v.distance); float newAngle = deltaAngle < 0.0f ? (float)this->angle - angle : (float)this->angle + angle; @@ -76,27 +89,30 @@ Polar Polar::operator+(Polar &v2) { Polar vector = Polar(newDistance, newAngle); return vector; } - -Polar Polar::operator-() { - Polar v = Polar(this->distance, this->angle + 180); - return v; +Polar Polar::operator+=(const Polar &v) { + *this = *this + v; + return *this; } -Polar Polar::operator-(Polar &v2) { - // Polar vector = *this + Polar(v2.distance, (float)v2.angle - 180); - //(Polar(v2.angle - 180, v2.distance)); - v2 = -v2; - return *this + v2; +Polar Passer::operator*(const Polar &v, float f) { + return Polar(v.distance * f, v.angle); } - -Polar Polar::operator*(float f) const { - return Polar(this->distance * f, - this->angle); // Polar(this->angle, this->distance * f); +Polar Passer::operator*(float f, const Polar &v) { + return Polar(v.distance * f, v.angle); } - -Polar Polar::operator/(const float &f) { - return Polar(this->distance / f, - this->angle); // Polar(this->angle, this->distance / f); +Polar Polar::operator*=(float f) { + this->distance *= f; + return *this; +} +Polar Passer::operator/(const Polar &v, float f) { + return Polar(v.distance / f, v.angle); +} +Polar Passer::operator/(float f, const Polar &v) { + return Polar(v.distance / f, v.angle); +} +Polar Polar::operator/=(float f) { + this->distance /= f; + return *this; } float Polar::Distance(const Polar &v1, const Polar &v2) { diff --git a/Polar.h b/Polar.h index f5ae017..82cbc05 100644 --- a/Polar.h +++ b/Polar.h @@ -13,8 +13,8 @@ struct Vector2; struct Spherical; /// @brief A polar vector -/// This will use the polar coordinate system consisting of a angle from a -/// reference direction and a distance. +/// @details This will use the polar coordinate system consisting of a angle +/// from a reference direction and a distance. struct Polar { public: /// @brief The distance in meters @@ -36,7 +36,6 @@ public: /// coordinates /// @param v The vector to convert Polar(Vector2 v); - /// @brief Convert a vector from spherical coordinates to polar coordinates /// @param s The vector to convert /// @note The resulting vector will be projected on the horizontal plane @@ -44,13 +43,21 @@ public: /// @brief A polar vector with zero degrees and distance const static Polar zero; + /// @brief A normalized forward-oriented vector + const static Polar forward; + /// @brief A normalized back-oriented vector + const static Polar back; + /// @brief A normalized right-oriented vector + const static Polar right; + /// @brief A normalized left-oriented vector + const static Polar left; /// @brief Equality test to another vector /// @param v The vector to check against /// @return true: if it is identical to the given vector /// @note This uses float comparison to check equality which may have strange /// effects. Equality on floats should be avoided. - bool operator==(const Polar &v); + bool operator==(const Polar &v) const; /// @brief The vector length /// @param v The vector for which you need the length @@ -71,27 +78,35 @@ public: /// @brief Negate the vector /// @return The negated vector /// This will rotate the vector by 180 degrees. Distance will stay the same. - Polar operator-(); + Polar operator-() const; + /// @brief Subtract a polar vector from this vector /// @param v The vector to subtract /// @return The result of the subtraction - Polar operator-(Polar &v); + Polar operator-(const Polar &v) const; + Polar operator-=(const Polar &v); /// @brief Add a polar vector to this vector /// @param v The vector to add /// @return The result of the addition - Polar operator+(Polar &v); + Polar operator+(const Polar &v) const; + Polar operator+=(const Polar &v); + /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - Polar operator*(float f) const; + friend Polar operator*(const Polar &v, float f); + friend Polar operator*(float f, const Polar &v); + Polar operator*=(float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled factor /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - Polar operator/(const float &f); + friend Polar operator/(const Polar &v, float f); + friend Polar operator/(float f, const Polar &v); + Polar operator/=(float f); /// @brief The distance between two vectors /// @param v1 The first vector diff --git a/Spherical.cpp b/Spherical.cpp index 3e623b3..6949720 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -43,13 +43,55 @@ Spherical::Spherical(Vector3 v) { } const Spherical Spherical::zero = Spherical(0.0f, 0.0f, 0.0f); +const Spherical Spherical::forward = Spherical(1.0f, 0.0f, 0.0f); +const Spherical Spherical::back = Spherical(1.0f, 180.0f, 0.0f); +const Spherical Spherical::right = Spherical(1.0f, 90.0f, 0.0f); +const Spherical Spherical::left = Spherical(1.0f, -90.0f, 0.0f); +const Spherical Spherical::up = Spherical(1.0f, 0.0f, 90.0f); +const Spherical Spherical::down = Spherical(1.0f, 0.0f, -90.0f); -Spherical Spherical::operator-() { +bool Spherical::operator==(const Spherical &v) const { + return (this->distance == v.distance && + this->horizontalAngle == v.horizontalAngle && + this->verticalAngle == v.verticalAngle); +} + +Spherical Spherical::Normalize(const Spherical &v) { + Spherical r = Spherical(1, v.horizontalAngle, v.verticalAngle); + return r; +} +Spherical Spherical::normalized() const { + Spherical r = Spherical(1, this->horizontalAngle, this->verticalAngle); + return r; +} + +Spherical Spherical::operator-() const { Spherical v = Spherical(this->distance, this->horizontalAngle + 180.0f, this->verticalAngle + 180.0f); return v; } +Spherical Passer::operator*(const Spherical &v, float f) { + return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); +} +Spherical Passer::operator*(float f, const Spherical &v) { + return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); +} +Spherical Spherical::operator*=(float f) { + this->distance *= f; + return *this; +} +Spherical Passer::operator/(const Spherical &v, float f) { + return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); +} +Spherical Passer::operator/(float f, const Spherical &v) { + return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); +} +Spherical Spherical::operator/=(float f) { + this->distance /= f; + return *this; +} + // float Spherical::GetSwing() { // // Not sure if this is correct // return sqrtf(horizontalAngle * horizontalAngle + @@ -59,4 +101,19 @@ Spherical Spherical::operator-() { // float Spherical::Distance(const Spherical &s1, const Spherical &s2) { // float d = 0; // return d; -// } \ No newline at end of file +// } + +Spherical Spherical::Rotate(const Spherical &v, Angle horizontalAngle, + Angle verticalAngle) { + Spherical r = Spherical(v.distance, v.horizontalAngle + horizontalAngle, + v.verticalAngle + verticalAngle); + return r; +} +Spherical Spherical::RotateHorizontal(const Spherical &v, Angle a) { + Spherical r = Spherical(v.distance, v.horizontalAngle + a, v.verticalAngle); + return r; +} +Spherical Spherical::RotateVertical(const Spherical &v, Angle a) { + Spherical r = Spherical(v.distance, v.horizontalAngle, v.verticalAngle + a); + return r; +} \ No newline at end of file diff --git a/Spherical.h b/Spherical.h index 9e9c73c..39be3db 100644 --- a/Spherical.h +++ b/Spherical.h @@ -1,6 +1,6 @@ -/// 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/. +// 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/. #ifndef SPHERICAL_H #define SPHERICAL_H @@ -13,8 +13,7 @@ namespace Passer { struct Vector3; /// @brief A spherical vector -/// @details -/// This is a vector in 3D space using a spherical coordinate system. +/// @details This is a vector in 3D space using a spherical coordinate system. /// It consists of a distance and the polar and elevation angles from a /// reference direction. The reference direction is typically thought of /// as a forward direction. @@ -48,12 +47,64 @@ public: /// @brief A spherical vector with zero degree angles and distance const static Spherical zero; + /// @brief A normalized forward-oriented vector + const static Spherical forward; + /// @brief A normalized back-oriented vector + const static Spherical back; + /// @brief A normalized right-oriented vector + const static Spherical right; + /// @brief A normalized left-oriented vector + const static Spherical left; + /// @brief A normalized up-oriented vector + const static Spherical up; + /// @brief A normalized down-oriented vector + const static Spherical down; + + /// @brief Equality test to another vector + /// @param v The vector to check against + /// @return true: if it is identical to the given vector + /// @note This uses float comparison to check equality which may have strange + /// effects. Equality on floats should be avoided. + bool operator==(const Spherical &v) const; + + /// @brief The vector length + /// @param v The vector for which you need the length + /// @return The vector length; + inline static float Magnitude(const Spherical &v) { return v.distance; } + /// @brief The vector length + /// @return The vector length + inline float magnitude() const { return this->distance; } + + /// @brief Convert the vector to a length of 1 + /// @param v The vector to convert + /// @return The vector normalized to a length of 1 + static Spherical Normalize(const Spherical &v); + /// @brief Convert the vector to a length of a + /// @return The vector normalized to a length of 1 + Spherical normalized() const; /// @brief Negate the vector /// @return The negated vector /// This will rotate the vector by 180 degrees horizontally and /// vertically. Distance will stay the same. - Spherical operator-(); + Spherical operator-() const; + + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend Spherical operator*(const Spherical &v, float f); + friend Spherical operator*(float f, const Spherical &v); + Spherical operator*=(float f); + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled factor + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend Spherical operator/(const Spherical &v, float f); + friend Spherical operator/(float f, const Spherical &v); + Spherical operator/=(float f); /// /// The distance between two vectors @@ -62,6 +113,11 @@ public: /// The second vector /// The distance between the two vectors // static float Distance(const Spherical &s1, const Spherical &s2); + + static Spherical Rotate(const Spherical &v, Angle horizontalAngle, + Angle verticalAngle); + static Spherical RotateHorizontal(const Spherical &v, Angle angle); + static Spherical RotateVertical(const Spherical &v, Angle angle); }; } // namespace Passer diff --git a/Vector2.cpp b/Vector2.cpp index 1ab580a..e792d18 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -99,24 +99,24 @@ Vector2 Vector2::operator+=(const Vector2 &v) { Vector2 Vector2::Scale(const Vector2 &v1, const Vector2 &v2) { return Vector2(v1.x * v2.x, v1.y * v2.y); } -Vector2 Passer::operator*(const Vector2 &v, const float f) { +Vector2 Passer::operator*(const Vector2 &v, float f) { return Vector2(v.x * f, v.y * f); } -Vector2 Passer::operator*(const float f, const Vector2 &v) { +Vector2 Passer::operator*(float f, const Vector2 &v) { return Vector2(v.x * f, v.y * f); } -Vector2 Vector2::operator*=(const float f) { +Vector2 Vector2::operator*=(float f) { this->x *= f; this->y *= f; return *this; } -Vector2 Passer::operator/(const Vector2 &v, const float f) { +Vector2 Passer::operator/(const Vector2 &v, float f) { return Vector2(v.x / f, v.y / f); } -Vector2 Passer::operator/(const float f, const Vector2 &v) { +Vector2 Passer::operator/(float f, const Vector2 &v) { return Vector2(v.x / f, v.y / f); } -Vector2 Vector2::operator/=(const float f) { +Vector2 Vector2::operator/=(float f) { this->x /= f; this->y /= f; return *this; diff --git a/Vector2.h b/Vector2.h index 055375a..c72ebd6 100644 --- a/Vector2.h +++ b/Vector2.h @@ -59,16 +59,14 @@ public: const static Vector2 zero; /// @brief A vector with one for all axis const static Vector2 one; + /// @brief A normalized forward-oriented vector + const static Vector2 forward; + /// @brief A normalized back-oriented vector + const static Vector2 back; /// @brief A normalized right-oriented vector const static Vector2 right; /// @brief A normalized left-oriented vector const static Vector2 left; - /// @brief A normalized forward-oriented vector - /// @note This is equal to Vector2::up - const static Vector2 forward; - /// @brief A normalized back-oriented vector - /// @note This is equal to Vector2::down - const static Vector2 back; /// @brief A normalized up-oriented vector /// @note This is a convenience function which is equal to Vector2::forward const static Vector2 up; @@ -139,16 +137,16 @@ public: /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - friend Vector2 operator*(const Vector2 &v, const float f); - friend Vector2 operator*(const float f, const Vector2 &v); - Vector2 operator*=(const float f); + friend Vector2 operator*(const Vector2 &v, float f); + friend Vector2 operator*(float f, const Vector2 &v); + Vector2 operator*=(float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - friend Vector2 operator/(const Vector2 &v, const float f); - friend Vector2 operator/(const float f, const Vector2 &v); - Vector2 operator/=(const float f); + friend Vector2 operator/(const Vector2 &v, float f); + friend Vector2 operator/(float f, const Vector2 &v); + Vector2 operator/=(float f); /// @brief The dot product of two vectors /// @param v1 The first vector diff --git a/Vector3.cpp b/Vector3.cpp index 2cf43f1..cfce278 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -118,25 +118,25 @@ Vector3 Vector3::operator+=(const Vector3 &v) { Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) { return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } -Vector3 Passer::operator*(const Vector3 &v, const float f) { +Vector3 Passer::operator*(const Vector3 &v, float f) { return Vector3(v.x * f, v.y * f, v.z * f); } -Vector3 Passer::operator*(const float f, const Vector3 &v) { +Vector3 Passer::operator*(float f, const Vector3 &v) { return Vector3(v.x * f, v.y * f, v.z * f); } -Vector3 Vector3::operator*=(const float f) { +Vector3 Vector3::operator*=(float f) { this->x *= f; this->y *= f; this->z *= f; return *this; } -Vector3 Passer::operator/(const Vector3 &v, const float f) { +Vector3 Passer::operator/(const Vector3 &v, float f) { return Vector3(v.x / f, v.y / f, v.z / f); } -Vector3 Passer::operator/(const float f, const Vector3 &v) { +Vector3 Passer::operator/(float f, const Vector3 &v) { return Vector3(v.x / f, v.y / f, v.z / f); } -Vector3 Vector3::operator/=(const float f) { +Vector3 Vector3::operator/=(float f) { this->x /= f; this->y /= f; this->z /= f; diff --git a/Vector3.h b/Vector3.h index 5c10bb6..9ac6715 100644 --- a/Vector3.h +++ b/Vector3.h @@ -64,6 +64,10 @@ public: const static Vector3 zero; /// @brief A vector with one for all axis const static Vector3 one; + /// @brief A normalized forward-oriented vector + const static Vector3 forward; + /// @brief A normalized back-oriented vector + const static Vector3 back; /// @brief A normalized right-oriented vector const static Vector3 right; /// @brief A normalized left-oriented vector @@ -72,10 +76,6 @@ public: const static Vector3 up; /// @brief A normalized down-oriented vector const static Vector3 down; - /// @brief A normalized forward-oriented vector - const static Vector3 forward; - /// @brief A normalized back-oriented vector - const static Vector3 back; // Access functions which are intended to replace the use of XYZ inline float Forward() const { return z; }; @@ -145,16 +145,16 @@ public: /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - friend Vector3 operator*(const Vector3 &v, const float f); - friend Vector3 operator*(const float f, const Vector3 &v); - Vector3 operator*=(const float f); + friend Vector3 operator*(const Vector3 &v, float f); + friend Vector3 operator*(float f, const Vector3 &v); + Vector3 operator*=(float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - friend Vector3 operator/(const Vector3 &v, const float f); - friend Vector3 operator/(const float f, const Vector3 &v); - Vector3 operator/=(const float f); + friend Vector3 operator/(const Vector3 &v, float f); + friend Vector3 operator/(float f, const Vector3 &v); + Vector3 operator/=(float f); /// @brief The distance between two vectors /// @param v1 The first vector diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 2598e7b..1c48cd7 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -116,6 +116,10 @@ TEST(Polar, Addition) { v2 = Polar::zero; r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; + + r = v1; + r += v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; } TEST(Polar, Scale_Multiply) { From ee62cbae3ec63b7847df242e02b453a43defa5de Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 14 May 2024 09:21:35 +0200 Subject: [PATCH 049/121] XYZ deprecation --- Axis.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Axis.cpp b/Axis.cpp index 0b21ac0..2fba93e 100644 --- a/Axis.cpp +++ b/Axis.cpp @@ -20,8 +20,8 @@ Axis::Axis(Angle horizontal, Angle vertical) { }; Axis::Axis(Vector3 v) { - this->horizontalAngle = atan2f(v.x, v.z) * Angle::Rad2Deg; - this->verticalAngle = 90 - acosf(v.y) * Angle::Rad2Deg; + this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; + this->verticalAngle = 90 - acosf(v.Up()) * Angle::Rad2Deg; } const Axis Axis::forward = Axis(0, 0); From 47a63689ff71631f76f6e551e427879f5dcc212b Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 14 May 2024 11:57:26 +0200 Subject: [PATCH 050/121] Fix Vector3 --- Axis.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Axis.h b/Axis.h index 0325257..7be4e70 100644 --- a/Axis.h +++ b/Axis.h @@ -9,7 +9,7 @@ namespace Passer { -class Vector3; +struct Vector3; class Axis { public: From 78468e38cd8d398f36213f8205b87ad41f798f74 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 14 May 2024 11:57:44 +0200 Subject: [PATCH 051/121] Renamed VectorAlgebra project to LinearAlgebra --- CMakeLists.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1591739..c0bcd5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(ESP_PLATFORM) INCLUDE_DIRS "." ) else() - project(VectorAlgebra) # Create project "simple_example" + project(LinearAlgebra) set(CMAKE_CXX_STANDARD 11) # Enable c++11 standard set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -22,7 +22,7 @@ else() FetchContent_MakeAvailable(googletest) include_directories(.) - add_library(VectorAlgebra STATIC + add_library(LinearAlgebra STATIC "FloatSingle.cpp" "Angle.cpp" "Vector2.cpp" @@ -31,12 +31,14 @@ else() "Polar.cpp" "Spherical.cpp" "Matrix.cpp" + "Axis.cpp" + "AngleAxis.cpp" ) enable_testing() add_executable( - VectorAlgebraTest + LinearAlgebraTest "test/Angle_test.cc" "test/FloatSingle_test.cc" "test/Vector2_test.cc" @@ -48,19 +50,19 @@ else() "test/DiscreteAngle_test.cc" ) target_link_libraries( - VectorAlgebraTest + LinearAlgebraTest gtest_main - VectorAlgebra + LinearAlgebra ) if(MSVC) - target_compile_options(VectorAlgebraTest PRIVATE /W4 /WX) + target_compile_options(LinearAlgebraTest PRIVATE /W4 /WX) else() - target_compile_options(VectorAlgebraTest PRIVATE -Wall -Wextra -Wpedantic -Werror) + target_compile_options(LinearAlgebraTest PRIVATE -Wall -Wextra -Wpedantic -Werror) endif() include(GoogleTest) - gtest_discover_tests(VectorAlgebraTest) + gtest_discover_tests(LinearAlgebraTest) endif() From 91c7b2086d26b1c67a6a85c4c8f80a325ba891f7 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 14 May 2024 12:02:36 +0200 Subject: [PATCH 052/121] Fix gitlab test runner --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6b28d70..40f9eec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ unit-test-job: - cmake --build . - export GTEST_OUTPUT="xml:report.xml" - ls -la - - "./VectorAlgebraTest" + - "./LinearAlgebraTest" artifacts: when: always reports: From f8009a7663d71f401a67b53c629eac8040069e52 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 23 May 2024 12:41:19 +0200 Subject: [PATCH 053/121] Updated namespace --- Angle.h | 4 +++- Angle16.h | 4 +++- Angle32.h | 5 ++++- Angle8.h | 4 +++- AngleAxis.h | 5 ++++- AngleUsing.h | 5 ++++- Axis.h | 5 ++++- FloatSingle.h | 5 ++++- Matrix.h | 5 ++++- Polar.h | 12 +++++++----- Quaternion.h | 5 ++++- Range.h | 5 ++++- Spherical.h | 4 +++- Vector2.h | 6 ++++-- Vector3.h | 4 +++- 15 files changed, 58 insertions(+), 20 deletions(-) diff --git a/Angle.h b/Angle.h index 943be90..3c55e48 100644 --- a/Angle.h +++ b/Angle.h @@ -6,6 +6,7 @@ #define ANGLE_H namespace Passer { +namespace LinearAlgebra { template class AngleOf { public: @@ -40,7 +41,8 @@ private: using Angle = AngleOf; +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #endif \ No newline at end of file diff --git a/Angle16.h b/Angle16.h index 47d31ce..511ab63 100644 --- a/Angle16.h +++ b/Angle16.h @@ -4,6 +4,7 @@ #include namespace Passer { +namespace LinearAlgebra { typedef AngleUsing Angle16; @@ -22,5 +23,6 @@ template <> float Angle16::ToFloat() const { return f; } +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; \ No newline at end of file +using namespace Passer::LinearAlgebra; \ No newline at end of file diff --git a/Angle32.h b/Angle32.h index cded359..72b135b 100644 --- a/Angle32.h +++ b/Angle32.h @@ -4,6 +4,8 @@ #include namespace Passer { +namespace LinearAlgebra { + typedef AngleUsing Angle32; template <> Angle32::AngleUsing(float angle) { @@ -21,5 +23,6 @@ template <> float Angle32::ToFloat() const { return f; } +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; \ No newline at end of file +using namespace Passer::LinearAlgebra; \ No newline at end of file diff --git a/Angle8.h b/Angle8.h index 5ba5f6e..53ba7d2 100644 --- a/Angle8.h +++ b/Angle8.h @@ -4,6 +4,7 @@ #include namespace Passer { +namespace LinearAlgebra { typedef AngleUsing Angle8; @@ -23,5 +24,6 @@ template <> float Angle8::ToFloat() const { return f; } +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; \ No newline at end of file +using namespace Passer::LinearAlgebra; \ No newline at end of file diff --git a/AngleAxis.h b/AngleAxis.h index b387521..9f64628 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -9,6 +9,7 @@ #include "Axis.h" namespace Passer { +namespace LinearAlgbra { class AngleAxis { public: @@ -18,7 +19,9 @@ public: AngleAxis(); AngleAxis(Angle angle, Axis axis); }; + +} // namespace LinearAlgbra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgbra; #endif \ No newline at end of file diff --git a/AngleUsing.h b/AngleUsing.h index ca179db..7afe51d 100644 --- a/AngleUsing.h +++ b/AngleUsing.h @@ -5,6 +5,7 @@ #include "Range.h" namespace Passer { +namespace LinearAlgebra { // A fixed angle between (-180..180] @@ -40,7 +41,9 @@ public: // protected: T value; }; + +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #endif diff --git a/Axis.h b/Axis.h index 7be4e70..ba49ddc 100644 --- a/Axis.h +++ b/Axis.h @@ -8,6 +8,7 @@ #include "Angle.h" namespace Passer { +namespace LinearAlgebra { struct Vector3; @@ -29,7 +30,9 @@ public: Vector3 ToVector3(); }; + +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgbra; #endif \ No newline at end of file diff --git a/FloatSingle.h b/FloatSingle.h index 8922f06..060cc8b 100644 --- a/FloatSingle.h +++ b/FloatSingle.h @@ -6,6 +6,7 @@ #define FLOAT_H namespace Passer { +namespace LinearAlgebra { class Float { public: @@ -14,7 +15,9 @@ public: static float Clamp(float f, float min, float max); }; + +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #endif diff --git a/Matrix.h b/Matrix.h index 3997464..33087aa 100644 --- a/Matrix.h +++ b/Matrix.h @@ -4,6 +4,7 @@ #include "Vector3.h" namespace Passer { +namespace LinearAlgebra { /// @brief Single precision float matrix template class MatrixOf { @@ -112,7 +113,9 @@ private: unsigned int cols; T *data; }; + +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #endif \ No newline at end of file diff --git a/Polar.h b/Polar.h index 82cbc05..ec9a2c7 100644 --- a/Polar.h +++ b/Polar.h @@ -8,6 +8,7 @@ #include "Angle.h" namespace Passer { +namespace LinearAlgebra { struct Vector2; struct Spherical; @@ -24,7 +25,8 @@ public: /// @remark The angle shall be between -180 .. 180 Angle angle; - /// @brief A new vector with polar coordinates with zero degrees and distance + /// @brief A new vector with polar coordinates with zero degrees and + /// distance Polar(); /// @brief A new vector with polar coordinates /// @param distance The distance in meters @@ -55,8 +57,8 @@ public: /// @brief Equality test to another vector /// @param v The vector to check against /// @return true: if it is identical to the given vector - /// @note This uses float comparison to check equality which may have strange - /// effects. Equality on floats should be avoided. + /// @note This uses float comparison to check equality which may have + /// strange effects. Equality on floats should be avoided. bool operator==(const Polar &v) const; /// @brief The vector length @@ -120,9 +122,9 @@ public: /// @return The rotated vector static Polar Rotate(const Polar &v, Angle a); }; - +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #include "Spherical.h" #include "Vector2.h" diff --git a/Quaternion.h b/Quaternion.h index 079128f..cc99a51 100644 --- a/Quaternion.h +++ b/Quaternion.h @@ -8,6 +8,7 @@ #include "Vector3.h" namespace Passer { +namespace LinearAlgebra { extern "C" { /// @@ -281,7 +282,9 @@ private: Vector3 xyz() const; }; + +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #endif diff --git a/Range.h b/Range.h index 59ac3f5..65f1dba 100644 --- a/Range.h +++ b/Range.h @@ -2,6 +2,7 @@ #define RANGE_H namespace Passer { +namespace LinearAlgebra { /* /// @brief Signed range. May be renamed to SignedRange later @@ -41,7 +42,9 @@ public: T value; }; + +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #endif \ No newline at end of file diff --git a/Spherical.h b/Spherical.h index 39be3db..dcad9f7 100644 --- a/Spherical.h +++ b/Spherical.h @@ -9,6 +9,7 @@ #include "Polar.h" namespace Passer { +namespace LinearAlgebra { struct Vector3; @@ -120,8 +121,9 @@ public: static Spherical RotateVertical(const Spherical &v, Angle angle); }; +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #include "Vector3.h" diff --git a/Vector2.h b/Vector2.h index c72ebd6..aeca26b 100644 --- a/Vector2.h +++ b/Vector2.h @@ -27,6 +27,7 @@ typedef struct Vec2 { } namespace Passer { +namespace LinearAlgebra { struct Vector3; struct Polar; @@ -178,7 +179,7 @@ public: /// @param v The vector to rotate /// @param a The angle in degrees to rotate /// @return The rotated vector - static Vector2 Rotate(const Vector2 &v, Passer::Angle a); + static Vector2 Rotate(const Vector2 &v, Passer::LinearAlgebra::Angle a); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector @@ -191,8 +192,9 @@ public: static Vector2 Lerp(const Vector2 &v1, const Vector2 &v2, float f); }; +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #include "Polar.h" diff --git a/Vector3.h b/Vector3.h index 9ac6715..27db549 100644 --- a/Vector3.h +++ b/Vector3.h @@ -8,6 +8,7 @@ #include "Vector2.h" namespace Passer { +namespace LinearAlgebra { struct Spherical; @@ -213,8 +214,9 @@ public: static Vector3 Lerp(const Vector3 &v1, const Vector3 &v2, float f); }; +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer; +using namespace Passer::LinearAlgebra; #include "Spherical.h" From a25a8be0670b8e3a53db38de9772cb04d73e8a5b Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 23 May 2024 12:46:39 +0200 Subject: [PATCH 054/121] Fixed namespace issues --- Angle.cpp | 3 ++- AngleAxis.h | 6 +++--- Axis.h | 2 +- Polar.cpp | 8 ++++---- Spherical.cpp | 8 ++++---- Vector2.cpp | 10 +++++----- Vector3.cpp | 8 ++++---- 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 3cb21e3..180db0f 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -78,7 +78,8 @@ template <> AngleOf AngleOf::pi = 3.1415927410125732421875F; template <> AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); template <> AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; -template <> bool Passer::AngleOf::operator==(AngleOf a) { +template <> +bool Passer::LinearAlgebra::AngleOf::operator==(AngleOf a) { return (float)*this == (float)a; } diff --git a/AngleAxis.h b/AngleAxis.h index 9f64628..7dd47ab 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -9,7 +9,7 @@ #include "Axis.h" namespace Passer { -namespace LinearAlgbra { +namespace LinearAlgebra { class AngleAxis { public: @@ -20,8 +20,8 @@ public: AngleAxis(Angle angle, Axis axis); }; -} // namespace LinearAlgbra +} // namespace LinearAlgebra } // namespace Passer -using namespace Passer::LinearAlgbra; +using namespace Passer::LinearAlgebra; #endif \ No newline at end of file diff --git a/Axis.h b/Axis.h index ba49ddc..4682af7 100644 --- a/Axis.h +++ b/Axis.h @@ -33,6 +33,6 @@ public: } // namespace LinearAlgebra } // namespace Passer -using namespace Passer::LinearAlgbra; +using namespace Passer::LinearAlgebra; #endif \ No newline at end of file diff --git a/Polar.cpp b/Polar.cpp index 1099a17..2be9547 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -94,20 +94,20 @@ Polar Polar::operator+=(const Polar &v) { return *this; } -Polar Passer::operator*(const Polar &v, float f) { +Polar Passer::LinearAlgebra::operator*(const Polar &v, float f) { return Polar(v.distance * f, v.angle); } -Polar Passer::operator*(float f, const Polar &v) { +Polar Passer::LinearAlgebra::operator*(float f, const Polar &v) { return Polar(v.distance * f, v.angle); } Polar Polar::operator*=(float f) { this->distance *= f; return *this; } -Polar Passer::operator/(const Polar &v, float f) { +Polar Passer::LinearAlgebra::operator/(const Polar &v, float f) { return Polar(v.distance / f, v.angle); } -Polar Passer::operator/(float f, const Polar &v) { +Polar Passer::LinearAlgebra::operator/(float f, const Polar &v) { return Polar(v.distance / f, v.angle); } Polar Polar::operator/=(float f) { diff --git a/Spherical.cpp b/Spherical.cpp index 6949720..5efef69 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -71,20 +71,20 @@ Spherical Spherical::operator-() const { return v; } -Spherical Passer::operator*(const Spherical &v, float f) { +Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); } -Spherical Passer::operator*(float f, const Spherical &v) { +Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) { return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); } Spherical Spherical::operator*=(float f) { this->distance *= f; return *this; } -Spherical Passer::operator/(const Spherical &v, float f) { +Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); } -Spherical Passer::operator/(float f, const Spherical &v) { +Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) { return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); } Spherical Spherical::operator/=(float f) { diff --git a/Vector2.cpp b/Vector2.cpp index e792d18..9c94fae 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -99,10 +99,10 @@ Vector2 Vector2::operator+=(const Vector2 &v) { Vector2 Vector2::Scale(const Vector2 &v1, const Vector2 &v2) { return Vector2(v1.x * v2.x, v1.y * v2.y); } -Vector2 Passer::operator*(const Vector2 &v, float f) { +Vector2 Passer::LinearAlgebra::operator*(const Vector2 &v, float f) { return Vector2(v.x * f, v.y * f); } -Vector2 Passer::operator*(float f, const Vector2 &v) { +Vector2 Passer::LinearAlgebra::operator*(float f, const Vector2 &v) { return Vector2(v.x * f, v.y * f); } Vector2 Vector2::operator*=(float f) { @@ -110,10 +110,10 @@ Vector2 Vector2::operator*=(float f) { this->y *= f; return *this; } -Vector2 Passer::operator/(const Vector2 &v, float f) { +Vector2 Passer::LinearAlgebra::operator/(const Vector2 &v, float f) { return Vector2(v.x / f, v.y / f); } -Vector2 Passer::operator/(float f, const Vector2 &v) { +Vector2 Passer::LinearAlgebra::operator/(float f, const Vector2 &v) { return Vector2(v.x / f, v.y / f); } Vector2 Vector2::operator/=(float f) { @@ -151,7 +151,7 @@ float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { return -(angleTo - angleFrom) * Angle::Rad2Deg; } -Vector2 Vector2::Rotate(const Vector2 &v, Passer::Angle a) { +Vector2 Vector2::Rotate(const Vector2 &v, Passer::LinearAlgebra::Angle a) { float angleRad = a * Angle::Deg2Rad; #if defined(AVR) float sinValue = sin(angleRad); diff --git a/Vector3.cpp b/Vector3.cpp index cfce278..da894f8 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -118,10 +118,10 @@ Vector3 Vector3::operator+=(const Vector3 &v) { Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) { return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } -Vector3 Passer::operator*(const Vector3 &v, float f) { +Vector3 Passer::LinearAlgebra::operator*(const Vector3 &v, float f) { return Vector3(v.x * f, v.y * f, v.z * f); } -Vector3 Passer::operator*(float f, const Vector3 &v) { +Vector3 Passer::LinearAlgebra::operator*(float f, const Vector3 &v) { return Vector3(v.x * f, v.y * f, v.z * f); } Vector3 Vector3::operator*=(float f) { @@ -130,10 +130,10 @@ Vector3 Vector3::operator*=(float f) { this->z *= f; return *this; } -Vector3 Passer::operator/(const Vector3 &v, float f) { +Vector3 Passer::LinearAlgebra::operator/(const Vector3 &v, float f) { return Vector3(v.x / f, v.y / f, v.z / f); } -Vector3 Passer::operator/(float f, const Vector3 &v) { +Vector3 Passer::LinearAlgebra::operator/(float f, const Vector3 &v) { return Vector3(v.x / f, v.y / f, v.z / f); } Vector3 Vector3::operator/=(float f) { From 2bad384611e7d999b4c421781dab8f1c4543fe93 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 17 Jun 2024 17:52:32 +0200 Subject: [PATCH 055/121] Added spherical addition --- Spherical.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++ Spherical.h | 8 ++++ test/Polar_test.cc | 7 +++- test/Spherical_test.cc | 25 ++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) diff --git a/Spherical.cpp b/Spherical.cpp index 5efef69..b521c77 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -71,6 +71,65 @@ Spherical Spherical::operator-() const { return v; } +Spherical Spherical::operator+(const Spherical &s2) const { + // let's do it the easy way... + Vector3 v1 = Vector3(*this); + Vector3 v2 = Vector3(s2); + Vector3 v = v1 + v2; + Spherical r = Spherical(v); + return r; + /* + // This is the hard way... + if (v2.distance <= 0) + return Spherical(this->distance, this->horizontalAngle, + this->verticalAngle); + if (this->distance <= 0) + return v2; + + float deltaHorizontalAngle = + (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); + float horizontalRotation = deltaHorizontalAngle < 0 + ? 180 + deltaHorizontalAngle + : 180 - deltaHorizontalAngle; + float deltaVerticalAngle = + Angle::Normalize(v2.verticalAngle - this->verticalAngle); + float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle + : 180 - deltaVerticalAngle; + + if (horizontalRotation == 180 && verticalRotation == 180) + // angle is too small, take this angle and add the distances + return Spherical(this->distance + v2.distance, this->horizontalAngle, + this->verticalAngle); + + Angle rotation = AngleBetween(*this, v2); + float newDistance = + Angle::CosineRuleSide(v2.distance, this->distance, rotation); + float angle = + Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); + + // Now we have to project the angle to the horizontal and vertical planes... + // The axis for the angle is the cross product of the two spherical vectors + // (which function we do not have either...) + float horizontalAngle = 0; + float verticalAngle = 0; + + float newHorizontalAngle = + deltaHorizontalAngle < 0 + ? Angle::Normalize(this->horizontalAngle - horizontalAngle) + : Angle::Normalize(this->horizontalAngle + horizontalAngle); + float newVerticalAngle = + deltaVerticalAngle < 0 + ? Angle::Normalize(this->verticalAngle - verticalAngle) + : Angle::Normalize(this->verticalAngle + verticalAngle); + + Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); + */ +} +Spherical Spherical::operator+=(const Spherical &v) { + *this = *this + v; + return *this; +} + Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); } @@ -103,6 +162,34 @@ Spherical Spherical::operator/=(float f) { // return d; // } +#include "AngleUsing.h" +#include "FloatSingle.h" +#include "Vector3.h" + +const float epsilon = 1E-05f; +const float Rad2Deg = 57.29578F; + +Angle Spherical::AngleBetween(const Spherical &v1, const Spherical &v2) { + + // float denominator = sqrtf(v1_3.sqrMagnitude() * v2_3.sqrMagnitude()); + float denominator = + v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * + // v2.distance * v2.distance); + if (denominator < epsilon) + return 0; + + Vector3 v1_3 = Vector3(v1); + Vector3 v2_3 = Vector3(v2); + float dot = Vector3::Dot(v1_3, v2_3); + float fraction = dot / denominator; + if (isnan(fraction)) + return fraction; // short cut to returning NaN universally + + float cdot = Float::Clamp(fraction, -1.0, 1.0); + float r = ((float)acos(cdot)) * Rad2Deg; + return r; +} + Spherical Spherical::Rotate(const Spherical &v, Angle horizontalAngle, Angle verticalAngle) { Spherical r = Spherical(v.distance, v.horizontalAngle + horizontalAngle, diff --git a/Spherical.h b/Spherical.h index dcad9f7..3bbf72e 100644 --- a/Spherical.h +++ b/Spherical.h @@ -90,6 +90,12 @@ public: /// vertically. Distance will stay the same. Spherical operator-() const; + /// @brief Add a spherical vector to this vector + /// @param v The vector to add + /// @return The result of the addition + Spherical operator+(const Spherical &v) const; + Spherical operator+=(const Spherical &v); + /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector @@ -115,6 +121,8 @@ public: /// The distance between the two vectors // static float Distance(const Spherical &s1, const Spherical &s2); + static Angle AngleBetween(const Spherical &v1, const Spherical &v2); + static Spherical Rotate(const Spherical &v, Angle horizontalAngle, Angle verticalAngle); static Spherical RotateHorizontal(const Spherical &v, Angle angle); diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 1c48cd7..8dfc18d 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -106,7 +106,7 @@ TEST(Polar, Subtraction) { } TEST(Polar, Addition) { - Polar v1 = Polar(4, 45); + Polar v1 = Polar(1, 45); Polar v2 = Polar(1, -90); Polar r = Polar::zero; @@ -120,6 +120,11 @@ TEST(Polar, Addition) { r = v1; r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; + + v2 = Polar(1, -45); + r = v1 + v2; + EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; + EXPECT_FLOAT_EQ(r.angle, 0) << "Addition(0 0 0)"; } TEST(Polar, Scale_Multiply) { diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index df8f18a..5e89ce2 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -128,4 +128,29 @@ TEST(Spherical, Incident2) { // EXPECT_NEAR(r.z, 5, 1.0e-06); } +TEST(Spherical, Addition) { + Spherical v1 = Spherical(1, 45, 0); + Spherical v2 = Spherical::zero; + Spherical r = Spherical::zero; + + r = v1 + v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; + + r = v1; + r += v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; + + v2 = Spherical(1, -45, 0); + r = v1 + v2; + EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; + EXPECT_FLOAT_EQ(r.horizontalAngle, 0) << "Addition(0 0 0)"; + EXPECT_FLOAT_EQ(r.verticalAngle, 0) << "Addition(0 0 0)"; + + v2 = Spherical(1, 0, 90); + r = v1 + v2; + EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontalAngle, 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.verticalAngle, 45) << "Addition(1 0 90)"; +} + #endif \ No newline at end of file From c70c079efc4fcfe9e9b2c29cd82f67faa63c827f Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 18 Jun 2024 11:45:38 +0200 Subject: [PATCH 056/121] Add spherical subtract --- Spherical.cpp | 14 ++++++++++++++ Spherical.h | 5 +++++ test/Spherical_test.cc | 6 +++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index b521c77..b09fda0 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -71,6 +71,19 @@ Spherical Spherical::operator-() const { return v; } +Spherical Spherical::operator-(const Spherical &s2) const { + // let's do it the easy way... + Vector3 v1 = Vector3(*this); + Vector3 v2 = Vector3(s2); + Vector3 v = v1 - v2; + Spherical r = Spherical(v); + return r; +} +Spherical Spherical::operator-=(const Spherical &v) { + *this = *this - v; + return *this; +} + Spherical Spherical::operator+(const Spherical &s2) const { // let's do it the easy way... Vector3 v1 = Vector3(*this); @@ -140,6 +153,7 @@ Spherical Spherical::operator*=(float f) { this->distance *= f; return *this; } + Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); } diff --git a/Spherical.h b/Spherical.h index 3bbf72e..4e285e3 100644 --- a/Spherical.h +++ b/Spherical.h @@ -90,6 +90,11 @@ public: /// vertically. Distance will stay the same. Spherical operator-() const; + /// @brief Subtract a spherical vector from this vector + /// @param v The vector to subtract + /// @return The result of the subtraction + Spherical operator-(const Spherical &v) const; + Spherical operator-=(const Spherical &v); /// @brief Add a spherical vector to this vector /// @param v The vector to add /// @return The result of the addition diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 5e89ce2..0ffae7f 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -142,9 +142,9 @@ TEST(Spherical, Addition) { v2 = Spherical(1, -45, 0); r = v1 + v2; - EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; - EXPECT_FLOAT_EQ(r.horizontalAngle, 0) << "Addition(0 0 0)"; - EXPECT_FLOAT_EQ(r.verticalAngle, 0) << "Addition(0 0 0)"; + EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontalAngle, 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.verticalAngle, 0) << "Addition(1 -45 0)"; v2 = Spherical(1, 0, 90); r = v1 + v2; From b81b77b1c95de8fda430a0bd428dd551c89db380 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 31 Jul 2024 11:44:23 +0200 Subject: [PATCH 057/121] Extend AngleOf support --- Angle.cpp | 31 +++++++++++++++------ Angle.h | 24 ++++++++++------- Angle16.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ Angle16.h | 34 +++++++++++------------ Angle32.h | 36 +++++++++++++------------ Angle8.cpp | 24 +++++++++++++++++ Angle8.h | 36 ++++++++++++------------- AngleUsing.h | 11 +++++--- Polar.cpp | 40 ++++++++++++++-------------- Polar.h | 40 +++++++++++++++++----------- Spherical.cpp | 55 +++++++++++++++++++------------------- Spherical.h | 47 +++++++++++++++++++------------- Vector2.cpp | 74 ++++++++++++++++++++++++++++----------------------- Vector2.h | 49 +++++++++++++++++++--------------- Vector3.cpp | 71 +++++++++++++++++++++++++----------------------- Vector3.h | 63 +++++++++++++++++++++++++------------------ 16 files changed, 441 insertions(+), 268 deletions(-) create mode 100644 Angle16.cpp create mode 100644 Angle8.cpp diff --git a/Angle.cpp b/Angle.cpp index 180db0f..4e69f45 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -3,8 +3,8 @@ // file, You can obtain one at https ://mozilla.org/MPL/2.0/. #include "Angle.h" -#include "FloatSingle.h" #include +#include "FloatSingle.h" /* const float Angle::Rad2Deg = 57.29578F; @@ -73,17 +73,29 @@ float Angle::SineRuleAngle(float a, float beta, float b) { */ //---------------------- -template <> AngleOf AngleOf::pi = 3.1415927410125732421875F; +template <> +AngleOf::AngleOf(float angle) : value(angle) {} -template <> AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); -template <> AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; +template <> +AngleOf::operator float() const { + return value; +} + +template <> +AngleOf AngleOf::pi = 3.1415927410125732421875F; + +template <> +AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); +template <> +AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; template <> bool Passer::LinearAlgebra::AngleOf::operator==(AngleOf a) { return (float)*this == (float)a; } -template <> AngleOf AngleOf::Normalize(AngleOf angle) { +template <> +AngleOf AngleOf::Normalize(AngleOf angle) { float angleValue = angle; if (!isfinite(angleValue)) return angleValue; @@ -96,7 +108,8 @@ template <> AngleOf AngleOf::Normalize(AngleOf angle) { } template <> -AngleOf AngleOf::Clamp(AngleOf angle, AngleOf min, +AngleOf AngleOf::Clamp(AngleOf angle, + AngleOf min, AngleOf max) { float normalizedAngle = Normalize(angle); float r = Float::Clamp(normalizedAngle, min, max); @@ -120,7 +133,8 @@ AngleOf AngleOf::MoveTowards(AngleOf fromAngle, } template <> -AngleOf AngleOf::CosineRuleSide(float a, float b, +AngleOf AngleOf::CosineRuleSide(float a, + float b, AngleOf gamma) { float a2 = a * a; float b2 = b * b; @@ -150,7 +164,8 @@ AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { } template <> -AngleOf AngleOf::SineRuleAngle(float a, AngleOf beta, +AngleOf AngleOf::SineRuleAngle(float a, + AngleOf beta, float b) { float alpha = asin(a * sin(beta * Angle::Deg2Rad) / b); return alpha; diff --git a/Angle.h b/Angle.h index 3c55e48..8be0583 100644 --- a/Angle.h +++ b/Angle.h @@ -8,11 +8,15 @@ namespace Passer { namespace LinearAlgebra { -template class AngleOf { -public: - AngleOf(){}; - AngleOf(T v) : value(v) {} - operator T() const { return value; } +template +class AngleOf { + public: + AngleOf() {}; + AngleOf(float f); + // AngleOf(T v) : value(v) {} + // operator T() const; // { return value; } + operator float() const; + inline T GetBinary() const { return this->value; } static AngleOf Rad2Deg; static AngleOf Deg2Rad; @@ -27,7 +31,8 @@ public: AngleOf r = Normalize(b - a); return r; }; - static AngleOf MoveTowards(AngleOf fromAngle, AngleOf toAngle, + static AngleOf MoveTowards(AngleOf fromAngle, + AngleOf toAngle, AngleOf maxAngle); static AngleOf CosineRuleSide(float a, float b, AngleOf gamma); @@ -35,14 +40,15 @@ public: static AngleOf SineRuleAngle(float a, AngleOf beta, float c); -private: + private: T value; }; using Angle = AngleOf; +// using Angle = AngleOf; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #endif \ No newline at end of file diff --git a/Angle16.cpp b/Angle16.cpp new file mode 100644 index 0000000..d30e208 --- /dev/null +++ b/Angle16.cpp @@ -0,0 +1,74 @@ +// 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 +#include "Angle.h" + +template <> +AngleOf::AngleOf(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); +} + +template <> +AngleOf::operator float() const { + float f = ((this->value * 180) / 32768.0F); + return f; +} + +// This should not exist... +// template <> +// AngleOf AngleOf::pi = 3.1415927410125732421875F; + +// template <> +// AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); +// template <> +// AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; + +// template <> +// AngleOf AngleOf::Normalize( +// AngleOf angle) { +// return angle; +// } + +// Not correct!!! just for syntactical compilation ATM +template <> +AngleOf AngleOf::CosineRuleSide( + float a, + float b, + AngleOf gamma) { + float a2 = a * a; + float b2 = b * b; + float d = a2 + b2 - 2 * a * b * cos(gamma * AngleOf::Deg2Rad); + // Catch edge cases where float inacuracies lead tot nans + if (d < 0) + return 0; + + float c = sqrtf(d); + return c; +} + +// Not correct!!! just for syntactical compilation ATM +template <> +AngleOf AngleOf::CosineRuleAngle(float a, + float b, + float c) { + float a2 = a * a; + float b2 = b * b; + float c2 = c * c; + float d = (a2 + b2 - c2) / (2 * a * b); + // Catch edge cases where float inacuracies lead tot nans + if (d >= 1) + return 0; + if (d <= -1) + return 180; + + float gamma = acos(d) * Angle::Rad2Deg; + return gamma; +} diff --git a/Angle16.h b/Angle16.h index 511ab63..c3f55e9 100644 --- a/Angle16.h +++ b/Angle16.h @@ -1,28 +1,28 @@ -#include "AngleUsing.h" +// #include "AngleUsing.h" -#include "Angle.h" #include +#include "Angle.h" namespace Passer { namespace LinearAlgebra { -typedef AngleUsing Angle16; +typedef AngleOf Angle16; -template <> Angle16::AngleUsing(float angle) { - if (!isfinite(angle)) { - value = 0; - return; - } +// template <> Angle16::AngleOf(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); -} +// // map float [-180..180) to integer [-32768..32767] +// this->value = (signed short)((angle / 360.0F) * 65536.0F); +// } -template <> float Angle16::ToFloat() const { - float f = ((this->value * 180) / 32768.0F); - return f; -} +// template <> float Angle16::ToFloat() const { +// float f = ((this->value * 180) / 32768.0F); +// return f; +// } -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; \ No newline at end of file diff --git a/Angle32.h b/Angle32.h index 72b135b..75a6e24 100644 --- a/Angle32.h +++ b/Angle32.h @@ -1,28 +1,30 @@ -#include "AngleUsing.h" +// #include "AngleUsing.h" -#include "Angle.h" #include +#include "Angle.h" namespace Passer { namespace LinearAlgebra { -typedef AngleUsing Angle32; +typedef AngleOf Angle32; -template <> Angle32::AngleUsing(float angle) { - if (!isfinite(angle)) { - value = 0; - return; - } +// template <> +// Angle32::AngleOf(float angle) { +// if (!isfinite(angle)) { +// value = 0; +// return; +// } - // map float [-180..180) to integer [-2147483648..2147483647] - this->value = (signed long)((angle / 360.0F) * 4294967295.0F); -} +// // map float [-180..180) to integer [-2147483648..2147483647] +// this->value = (signed long)((angle / 360.0F) * 4294967295.0F); +// } -template <> float Angle32::ToFloat() const { - float f = ((this->value * 180) / 2147483648.0F); - return f; -} +// template <> +// float Angle32::ToFloat() const { +// float f = ((this->value * 180) / 2147483648.0F); +// return f; +// } -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; \ No newline at end of file diff --git a/Angle8.cpp b/Angle8.cpp new file mode 100644 index 0000000..a992466 --- /dev/null +++ b/Angle8.cpp @@ -0,0 +1,24 @@ +// 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 +#include "Angle.h" + +template <> +AngleOf::AngleOf(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); +} + +template <> +AngleOf::operator float() const { + float f = (this->value * 180) / 128.0F; + return f; +} diff --git a/Angle8.h b/Angle8.h index 53ba7d2..580c0af 100644 --- a/Angle8.h +++ b/Angle8.h @@ -1,29 +1,29 @@ -#include "AngleUsing.h" +// #include "AngleUsing.h" -#include "Angle.h" #include +#include "Angle.h" namespace Passer { namespace LinearAlgebra { -typedef AngleUsing Angle8; +typedef AngleOf Angle8; -template <> Angle8::AngleUsing(float angle) { - if (!isfinite(angle)) { - value = 0; - return; - } +// template <> Angle8::AngleOf(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); -} +// // map float [-180..180) to integer [-128..127] +// float f = angle / 360.0F; +// this->value = (signed char)(f * 256.0F); +// } -template <> float Angle8::ToFloat() const { - float f = (this->value * 180) / 128.0F; - return f; -} +// template <> float Angle8::ToFloat() const { +// float f = (this->value * 180) / 128.0F; +// return f; +// } -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; \ No newline at end of file diff --git a/AngleUsing.h b/AngleUsing.h index 7afe51d..f2bc80e 100644 --- a/AngleUsing.h +++ b/AngleUsing.h @@ -1,3 +1,4 @@ +/* #ifndef DISCRETEANGLE_H #define DISCRETEANGLE_H @@ -9,8 +10,9 @@ namespace LinearAlgebra { // A fixed angle between (-180..180] -template class AngleUsing { -public: +template +class AngleUsing { + public: AngleUsing(T sourceValue) { this->value = sourceValue; } AngleUsing(float f); float ToFloat() const; @@ -42,8 +44,9 @@ public: T value; }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #endif +*/ \ No newline at end of file diff --git a/Polar.cpp b/Polar.cpp index 2be9547..8bebaf1 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -37,11 +37,11 @@ const Polar Polar::back = Polar(1.0, 180.0f); const Polar Polar::right = Polar(1.0, 90.0f); const Polar Polar::left = Polar(1.0, -90.0f); -bool Polar::operator==(const Polar &v) const { +bool Polar::operator==(const Polar& v) const { return (this->distance == v.distance && this->angle == v.angle); } -Polar Polar::Normalize(const Polar &v) { +Polar Polar::Normalize(const Polar& v) { Polar r = Polar(1, v.angle); return r; } @@ -55,15 +55,15 @@ Polar Polar::operator-() const { return v; } -Polar Polar::operator-(const Polar &v) const { +Polar Polar::operator-(const Polar& v) const { Polar r = -v; return *this + r; } -Polar Polar::operator-=(const Polar &v) { +Polar Polar::operator-=(const Polar& v) { *this = *this - v; return *this; } -Polar Polar::operator+(const Polar &v) const { +Polar Polar::operator+(const Polar& v) const { if (v.distance == 0) return Polar(this->distance, this->angle); if (this->distance == 0.0f) @@ -89,39 +89,39 @@ Polar Polar::operator+(const Polar &v) const { Polar vector = Polar(newDistance, newAngle); return vector; } -Polar Polar::operator+=(const Polar &v) { +Polar Polar::operator+=(const Polar& v) { *this = *this + v; return *this; } -Polar Passer::LinearAlgebra::operator*(const Polar &v, float f) { - return Polar(v.distance * f, v.angle); -} -Polar Passer::LinearAlgebra::operator*(float f, const Polar &v) { - return Polar(v.distance * f, v.angle); -} +// Polar Passer::LinearAlgebra::operator*(const Polar &v, float f) { +// return Polar(v.distance * f, v.angle); +// } +// Polar Passer::LinearAlgebra::operator*(float f, const Polar &v) { +// return Polar(v.distance * f, v.angle); +// } Polar Polar::operator*=(float f) { this->distance *= f; return *this; } -Polar Passer::LinearAlgebra::operator/(const Polar &v, float f) { - return Polar(v.distance / f, v.angle); -} -Polar Passer::LinearAlgebra::operator/(float f, const Polar &v) { - return Polar(v.distance / f, v.angle); -} +// Polar Passer::LinearAlgebra::operator/(const Polar& v, float f) { +// return Polar(v.distance / f, v.angle); +// } +// Polar Passer::LinearAlgebra::operator/(float f, const Polar& v) { +// return Polar(v.distance / f, v.angle); +// } Polar Polar::operator/=(float f) { this->distance /= f; return *this; } -float Polar::Distance(const Polar &v1, const Polar &v2) { +float Polar::Distance(const Polar& v1, const Polar& v2) { float d = Angle::CosineRuleSide(v1.distance, v2.distance, (float)v2.angle - (float)v1.angle); return d; } -Polar Polar::Rotate(const Polar &v, Angle angle) { +Polar Polar::Rotate(const Polar& v, Angle angle) { Angle a = Angle::Normalize(v.angle + angle); Polar r = Polar(v.distance, a); return r; diff --git a/Polar.h b/Polar.h index ec9a2c7..d6eb5ff 100644 --- a/Polar.h +++ b/Polar.h @@ -17,7 +17,7 @@ struct Spherical; /// @details This will use the polar coordinate system consisting of a angle /// from a reference direction and a distance. struct Polar { -public: + public: /// @brief The distance in meters /// @remark The distance shall never be negative float distance; @@ -59,12 +59,12 @@ public: /// @return true: if it is identical to the given vector /// @note This uses float comparison to check equality which may have /// strange effects. Equality on floats should be avoided. - bool operator==(const Polar &v) const; + bool operator==(const Polar& v) const; /// @brief The vector length /// @param v The vector for which you need the length /// @return The vector length; - inline static float Magnitude(const Polar &v) { return v.distance; } + inline static float Magnitude(const Polar& v) { return v.distance; } /// @brief The vector length /// @return The vector length inline float magnitude() const { return this->distance; } @@ -72,7 +72,7 @@ public: /// @brief Convert the vector to a length of 1 /// @param v The vector to convert /// @return The vector normalized to a length of 1 - static Polar Normalize(const Polar &v); + static Polar Normalize(const Polar& v); /// @brief Convert the vector to a length of a /// @return The vector normalized to a length of 1 Polar normalized() const; @@ -85,45 +85,53 @@ public: /// @brief Subtract a polar vector from this vector /// @param v The vector to subtract /// @return The result of the subtraction - Polar operator-(const Polar &v) const; - Polar operator-=(const Polar &v); + Polar operator-(const Polar& v) const; + Polar operator-=(const Polar& v); /// @brief Add a polar vector to this vector /// @param v The vector to add /// @return The result of the addition - Polar operator+(const Polar &v) const; - Polar operator+=(const Polar &v); + Polar operator+(const Polar& v) const; + Polar operator+=(const Polar& v); /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend Polar operator*(const Polar &v, float f); - friend Polar operator*(float f, const Polar &v); + friend Polar operator*(const Polar& v, float f) { + return Polar(v.distance * f, v.angle); + } + friend Polar operator*(float f, const Polar& v) { + return Polar(f * v.distance, v.angle); + } Polar operator*=(float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled factor /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend Polar operator/(const Polar &v, float f); - friend Polar operator/(float f, const Polar &v); + friend Polar operator/(const Polar& v, float f) { + return Polar(v.distance / f, v.angle); + } + friend Polar operator/(float f, const Polar& v) { + return Polar(f / v.distance, v.angle); + } Polar operator/=(float f); /// @brief The distance between two vectors /// @param v1 The first vector /// @param v2 The second vector /// @return The distance between the two vectors - static float Distance(const Polar &v1, const Polar &v2); + static float Distance(const Polar& v1, const Polar& v2); /// @brief Rotate a vector /// @param v The vector to rotate /// @param a The angle in degreesto rotate /// @return The rotated vector - static Polar Rotate(const Polar &v, Angle a); + static Polar Rotate(const Polar& v, Angle a); }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #include "Spherical.h" diff --git a/Spherical.cpp b/Spherical.cpp index b09fda0..860b621 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -17,7 +17,8 @@ Spherical::Spherical(Polar polar) { this->verticalAngle = 0.0f; } -Spherical::Spherical(float distance, Angle horizontalAngle, +Spherical::Spherical(float distance, + Angle horizontalAngle, Angle verticalAngle) { if (distance < 0) { this->distance = -distance; @@ -50,13 +51,13 @@ const Spherical Spherical::left = Spherical(1.0f, -90.0f, 0.0f); const Spherical Spherical::up = Spherical(1.0f, 0.0f, 90.0f); const Spherical Spherical::down = Spherical(1.0f, 0.0f, -90.0f); -bool Spherical::operator==(const Spherical &v) const { +bool Spherical::operator==(const Spherical& v) const { return (this->distance == v.distance && this->horizontalAngle == v.horizontalAngle && this->verticalAngle == v.verticalAngle); } -Spherical Spherical::Normalize(const Spherical &v) { +Spherical Spherical::Normalize(const Spherical& v) { Spherical r = Spherical(1, v.horizontalAngle, v.verticalAngle); return r; } @@ -71,7 +72,7 @@ Spherical Spherical::operator-() const { return v; } -Spherical Spherical::operator-(const Spherical &s2) const { +Spherical Spherical::operator-(const Spherical& s2) const { // let's do it the easy way... Vector3 v1 = Vector3(*this); Vector3 v2 = Vector3(s2); @@ -79,12 +80,12 @@ Spherical Spherical::operator-(const Spherical &s2) const { Spherical r = Spherical(v); return r; } -Spherical Spherical::operator-=(const Spherical &v) { +Spherical Spherical::operator-=(const Spherical& v) { *this = *this - v; return *this; } -Spherical Spherical::operator+(const Spherical &s2) const { +Spherical Spherical::operator+(const Spherical& s2) const { // let's do it the easy way... Vector3 v1 = Vector3(*this); Vector3 v2 = Vector3(s2); @@ -138,28 +139,28 @@ Spherical Spherical::operator+(const Spherical &s2) const { Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); */ } -Spherical Spherical::operator+=(const Spherical &v) { +Spherical Spherical::operator+=(const Spherical& v) { *this = *this + v; return *this; } -Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { - return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); -} -Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) { - return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); -} +// Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { +// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); +// } +// Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) { +// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); +// } Spherical Spherical::operator*=(float f) { this->distance *= f; return *this; } -Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { - return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); -} -Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) { - return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); -} +// Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { +// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); +// } +// Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) { +// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); +// } Spherical Spherical::operator/=(float f) { this->distance /= f; return *this; @@ -183,12 +184,11 @@ Spherical Spherical::operator/=(float f) { const float epsilon = 1E-05f; const float Rad2Deg = 57.29578F; -Angle Spherical::AngleBetween(const Spherical &v1, const Spherical &v2) { - +Angle Spherical::AngleBetween(const Spherical& v1, const Spherical& v2) { // float denominator = sqrtf(v1_3.sqrMagnitude() * v2_3.sqrMagnitude()); float denominator = - v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * - // v2.distance * v2.distance); + v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * + // v2.distance * v2.distance); if (denominator < epsilon) return 0; @@ -197,24 +197,25 @@ Angle Spherical::AngleBetween(const Spherical &v1, const Spherical &v2) { float dot = Vector3::Dot(v1_3, v2_3); float fraction = dot / denominator; if (isnan(fraction)) - return fraction; // short cut to returning NaN universally + return fraction; // short cut to returning NaN universally float cdot = Float::Clamp(fraction, -1.0, 1.0); float r = ((float)acos(cdot)) * Rad2Deg; return r; } -Spherical Spherical::Rotate(const Spherical &v, Angle horizontalAngle, +Spherical Spherical::Rotate(const Spherical& v, + Angle horizontalAngle, Angle verticalAngle) { Spherical r = Spherical(v.distance, v.horizontalAngle + horizontalAngle, v.verticalAngle + verticalAngle); return r; } -Spherical Spherical::RotateHorizontal(const Spherical &v, Angle a) { +Spherical Spherical::RotateHorizontal(const Spherical& v, Angle a) { Spherical r = Spherical(v.distance, v.horizontalAngle + a, v.verticalAngle); return r; } -Spherical Spherical::RotateVertical(const Spherical &v, Angle a) { +Spherical Spherical::RotateVertical(const Spherical& v, Angle a) { Spherical r = Spherical(v.distance, v.horizontalAngle, v.verticalAngle + a); return r; } \ No newline at end of file diff --git a/Spherical.h b/Spherical.h index 4e285e3..112f5e0 100644 --- a/Spherical.h +++ b/Spherical.h @@ -19,7 +19,7 @@ struct Vector3; /// reference direction. The reference direction is typically thought of /// as a forward direction. struct Spherical { -public: + public: /// @brief The distance in meters /// @remark The distance should never be negative float distance; @@ -66,12 +66,12 @@ public: /// @return true: if it is identical to the given vector /// @note This uses float comparison to check equality which may have strange /// effects. Equality on floats should be avoided. - bool operator==(const Spherical &v) const; + bool operator==(const Spherical& v) const; /// @brief The vector length /// @param v The vector for which you need the length /// @return The vector length; - inline static float Magnitude(const Spherical &v) { return v.distance; } + inline static float Magnitude(const Spherical& v) { return v.distance; } /// @brief The vector length /// @return The vector length inline float magnitude() const { return this->distance; } @@ -79,7 +79,7 @@ public: /// @brief Convert the vector to a length of 1 /// @param v The vector to convert /// @return The vector normalized to a length of 1 - static Spherical Normalize(const Spherical &v); + static Spherical Normalize(const Spherical& v); /// @brief Convert the vector to a length of a /// @return The vector normalized to a length of 1 Spherical normalized() const; @@ -93,29 +93,39 @@ public: /// @brief Subtract a spherical vector from this vector /// @param v The vector to subtract /// @return The result of the subtraction - Spherical operator-(const Spherical &v) const; - Spherical operator-=(const Spherical &v); + Spherical operator-(const Spherical& v) const; + Spherical operator-=(const Spherical& v); /// @brief Add a spherical vector to this vector /// @param v The vector to add /// @return The result of the addition - Spherical operator+(const Spherical &v) const; - Spherical operator+=(const Spherical &v); + Spherical operator+(const Spherical& v) const; + Spherical operator+=(const Spherical& v); /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend Spherical operator*(const Spherical &v, float f); - friend Spherical operator*(float f, const Spherical &v); + friend Spherical operator*(const Spherical& v, float f) { + return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); + } + friend Spherical operator*(float f, const Spherical& v) { + return Spherical(v.distance * f, v.horizontalAngle, + v.verticalAngle); // not correct, should be f * v.distance + } Spherical operator*=(float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled factor /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend Spherical operator/(const Spherical &v, float f); - friend Spherical operator/(float f, const Spherical &v); + friend Spherical operator/(const Spherical& v, float f) { + return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); + } + friend Spherical operator/(float f, const Spherical& v) { + return Spherical(v.distance / f, v.horizontalAngle, + v.verticalAngle); // not correct, should be f / v.distance + } Spherical operator/=(float f); /// @@ -126,16 +136,17 @@ public: /// The distance between the two vectors // static float Distance(const Spherical &s1, const Spherical &s2); - static Angle AngleBetween(const Spherical &v1, const Spherical &v2); + static Angle AngleBetween(const Spherical& v1, const Spherical& v2); - static Spherical Rotate(const Spherical &v, Angle horizontalAngle, + static Spherical Rotate(const Spherical& v, + Angle horizontalAngle, Angle verticalAngle); - static Spherical RotateHorizontal(const Spherical &v, Angle angle); - static Spherical RotateVertical(const Spherical &v, Angle angle); + static Spherical RotateHorizontal(const Spherical& v, Angle angle); + static Spherical RotateVertical(const Spherical& v, Angle angle); }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #include "Vector3.h" diff --git a/Vector2.cpp b/Vector2.cpp index 9c94fae..a7ded06 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -26,8 +26,8 @@ Vector2::Vector2(float _x, float _y) { // y = v.y; // } Vector2::Vector2(Vector3 v) { - x = v.Right(); // x; - y = v.Forward(); // z; + x = v.Right(); // x; + y = v.Forward(); // z; } Vector2::Vector2(Polar p) { float horizontalRad = p.angle * Angle::Deg2Rad; @@ -49,18 +49,24 @@ const Vector2 Vector2::down = Vector2(0, -1); const Vector2 Vector2::forward = Vector2(0, 1); const Vector2 Vector2::back = Vector2(0, -1); -bool Vector2::operator==(const Vector2 &v) { +bool Vector2::operator==(const Vector2& v) { return (this->x == v.x && this->y == v.y); } -float Vector2::Magnitude(const Vector2 &v) { +float Vector2::Magnitude(const Vector2& v) { return sqrtf(v.x * v.x + v.y * v.y); } -float Vector2::magnitude() const { return (float)sqrtf(x * x + y * y); } -float Vector2::SqrMagnitude(const Vector2 &v) { return v.x * v.x + v.y * v.y; } -float Vector2::sqrMagnitude() const { return (x * x + y * y); } +float Vector2::magnitude() const { + return (float)sqrtf(x * x + y * y); +} +float Vector2::SqrMagnitude(const Vector2& v) { + return v.x * v.x + v.y * v.y; +} +float Vector2::sqrMagnitude() const { + return (x * x + y * y); +} -Vector2 Vector2::Normalize(const Vector2 &v) { +Vector2 Vector2::Normalize(const Vector2& v) { float num = Vector2::Magnitude(v); Vector2 result = Vector2::zero; if (num > Float::epsilon) { @@ -77,63 +83,65 @@ Vector2 Vector2::normalized() const { return result; } -Vector2 Vector2::operator-() { return Vector2(-this->x, -this->y); } +Vector2 Vector2::operator-() { + return Vector2(-this->x, -this->y); +} -Vector2 Vector2::operator-(const Vector2 &v) const { +Vector2 Vector2::operator-(const Vector2& v) const { return Vector2(this->x - v.x, this->y - v.y); } -Vector2 Vector2::operator-=(const Vector2 &v) { +Vector2 Vector2::operator-=(const Vector2& v) { this->x -= v.x; this->y -= v.y; return *this; } -Vector2 Vector2::operator+(const Vector2 &v) const { +Vector2 Vector2::operator+(const Vector2& v) const { return Vector2(this->x + v.x, this->y + v.y); } -Vector2 Vector2::operator+=(const Vector2 &v) { +Vector2 Vector2::operator+=(const Vector2& v) { this->x += v.x; this->y += v.y; return *this; } -Vector2 Vector2::Scale(const Vector2 &v1, const Vector2 &v2) { +Vector2 Vector2::Scale(const Vector2& v1, const Vector2& v2) { return Vector2(v1.x * v2.x, v1.y * v2.y); } -Vector2 Passer::LinearAlgebra::operator*(const Vector2 &v, float f) { - return Vector2(v.x * f, v.y * f); -} -Vector2 Passer::LinearAlgebra::operator*(float f, const Vector2 &v) { - return Vector2(v.x * f, v.y * f); -} +// Vector2 Passer::LinearAlgebra::operator*(const Vector2 &v, float f) { +// return Vector2(v.x * f, v.y * f); +// } +// Vector2 Passer::LinearAlgebra::operator*(float f, const Vector2 &v) { +// return Vector2(v.x * f, v.y * f); +// } Vector2 Vector2::operator*=(float f) { this->x *= f; this->y *= f; return *this; } -Vector2 Passer::LinearAlgebra::operator/(const Vector2 &v, float f) { - return Vector2(v.x / f, v.y / f); -} -Vector2 Passer::LinearAlgebra::operator/(float f, const Vector2 &v) { - return Vector2(v.x / f, v.y / f); -} +// Vector2 Passer::LinearAlgebra::operator/(const Vector2 &v, float f) { +// return Vector2(v.x / f, v.y / f); +// } +// Vector2 Passer::LinearAlgebra::operator/(float f, const Vector2 &v) { +// return Vector2(v.x / f, v.y / f); +// } Vector2 Vector2::operator/=(float f) { this->x /= f; this->y /= f; return *this; } -float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) { +float Vector2::Dot(const Vector2& v1, const Vector2& v2) { return v1.x * v2.x + v1.y * v2.y; } -float Vector2::Distance(const Vector2 &v1, const Vector2 &v2) { +float Vector2::Distance(const Vector2& v1, const Vector2& v2) { return Magnitude(v1 - v2); } -float Vector2::Angle(const Vector2 &v1, const Vector2 &v2) { +float Vector2::Angle(const Vector2& v1, const Vector2& v2) { return (float)fabs(SignedAngle(v1, v2)); } -float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { +float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) { float sqrMagFrom = v1.sqrMagnitude(); float sqrMagTo = v2.sqrMagnitude(); @@ -151,11 +159,11 @@ float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { return -(angleTo - angleFrom) * Angle::Rad2Deg; } -Vector2 Vector2::Rotate(const Vector2 &v, Passer::LinearAlgebra::Angle a) { +Vector2 Vector2::Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a) { float angleRad = a * Angle::Deg2Rad; #if defined(AVR) float sinValue = sin(angleRad); - float cosValue = cos(angleRad); // * Angle::Deg2Rad); + float cosValue = cos(angleRad); // * Angle::Deg2Rad); #else float sinValue = (float)sinf(angleRad); float cosValue = (float)cosf(angleRad); @@ -168,7 +176,7 @@ Vector2 Vector2::Rotate(const Vector2 &v, Passer::LinearAlgebra::Angle a) { return r; } -Vector2 Vector2::Lerp(const Vector2 &v1, const Vector2 &v2, float f) { +Vector2 Vector2::Lerp(const Vector2& v1, const Vector2& v2, float f) { Vector2 v = v1 + (v2 - v1) * f; return v; } diff --git a/Vector2.h b/Vector2.h index aeca26b..97d6c79 100644 --- a/Vector2.h +++ b/Vector2.h @@ -38,7 +38,7 @@ struct Polar; struct Vector2 : Vec2 { friend struct Vec2; -public: + public: /// @brief A new 2-dimensional zero vector Vector2(); /// @brief A new 2-dimensional vector @@ -80,12 +80,12 @@ public: /// @return true if it is identical to the given vector /// @note This uses float comparison to check equality which may have strange /// effects. Equality on floats should be avoided. - bool operator==(const Vector2 &v); + bool operator==(const Vector2& v); /// @brief The vector length /// @param v The vector for which you need the length /// @return The vector length - static float Magnitude(const Vector2 &v); + static float Magnitude(const Vector2& v); /// @brief The vector length /// @return The vector length float magnitude() const; @@ -95,7 +95,7 @@ public: /// @remark The squared length is computationally simpler than the real /// length. Think of Pythagoras A^2 + B^2 = C^2. This prevents the calculation /// of the squared root of C. - static float SqrMagnitude(const Vector2 &v); + static float SqrMagnitude(const Vector2& v); /// @brief The squared vector length /// @return The squared vector length /// @remark The squared length is computationally simpler than the real @@ -106,7 +106,7 @@ public: /// @brief Convert the vector to a length of 1 /// @param v The vector to convert /// @return The vector normalized to a length of 1 - static Vector2 Normalize(const Vector2 &v); + static Vector2 Normalize(const Vector2& v); /// @brief Convert the vector to a length 1 /// @return The vector normalized to a length of 1 Vector2 normalized() const; @@ -118,13 +118,13 @@ public: /// @brief Subtract a vector from this vector /// @param v The vector to subtract from this vector /// @return The result of the subtraction - Vector2 operator-(const Vector2 &v) const; - Vector2 operator-=(const Vector2 &v); + Vector2 operator-(const Vector2& v) const; + Vector2 operator-=(const Vector2& v); /// @brief Add a vector to this vector /// @param v The vector to add to this vector /// @return The result of the addition - Vector2 operator+(const Vector2 &v) const; - Vector2 operator+=(const Vector2 &v); + Vector2 operator+(const Vector2& v) const; + Vector2 operator+=(const Vector2& v); /// @brief Scale the vector using another vector /// @param v1 The vector to scale @@ -132,34 +132,39 @@ public: /// @return The scaled vector /// @remark Each component of the vector v1 will be multiplied with the /// matching component from the scaling vector v2. - static Vector2 Scale(const Vector2 &v1, const Vector2 &v2); + static Vector2 Scale(const Vector2& v1, const Vector2& v2); /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - friend Vector2 operator*(const Vector2 &v, float f); - friend Vector2 operator*(float f, const Vector2 &v); + friend Vector2 operator*(const Vector2& v, float f) { + return Vector2(v.x * f, v.y * f); + } + friend Vector2 operator*(float f, const Vector2& v) { + return Vector2(v.x * f, v.y * f); + // return Vector2(f * v.x, f * v.y); + } Vector2 operator*=(float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - friend Vector2 operator/(const Vector2 &v, float f); - friend Vector2 operator/(float f, const Vector2 &v); + friend Vector2 operator/(const Vector2& v, float f); + friend Vector2 operator/(float f, const Vector2& v); Vector2 operator/=(float f); /// @brief The dot product of two vectors /// @param v1 The first vector /// @param v2 The second vector /// @return The dot product of the two vectors - static float Dot(const Vector2 &v1, const Vector2 &v2); + static float Dot(const Vector2& v1, const Vector2& v2); /// @brief The distance between two vectors /// @param v1 The first vector /// @param v2 The second vector /// @return The distance between the two vectors - static float Distance(const Vector2 &v1, const Vector2 &v2); + static float Distance(const Vector2& v1, const Vector2& v2); /// @brief The angle between two vectors /// @param v1 The first vector @@ -168,18 +173,18 @@ public: /// @remark This reterns an unsigned angle which is the shortest distance /// between the two vectors. Use Vector2::SignedAngle if a signed angle is /// needed. - static float Angle(const Vector2 &v1, const Vector2 &v2); + static float Angle(const Vector2& v1, const Vector2& v2); /// @brief The signed angle between two vectors /// @param v1 The starting vector /// @param v2 The ending vector /// @return The signed angle between the two vectors - static float SignedAngle(const Vector2 &v1, const Vector2 &v2); + static float SignedAngle(const Vector2& v1, const Vector2& v2); /// @brief Rotate the vector /// @param v The vector to rotate /// @param a The angle in degrees to rotate /// @return The rotated vector - static Vector2 Rotate(const Vector2 &v, Passer::LinearAlgebra::Angle a); + static Vector2 Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector @@ -189,11 +194,11 @@ public: /// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value /// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference /// between *v1* and *v2* etc. - static Vector2 Lerp(const Vector2 &v1, const Vector2 &v2, float f); + static Vector2 Lerp(const Vector2& v1, const Vector2& v2, float f); }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #include "Polar.h" diff --git a/Vector3.cpp b/Vector3.cpp index da894f8..50829d7 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -65,17 +65,21 @@ const Vector3 Vector3::back = Vector3(0, 0, -1); // return Vector3(v.x, 0, v.y); // } -float Vector3::Magnitude(const Vector3 &v) { +float Vector3::Magnitude(const Vector3& v) { return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); } -float Vector3::magnitude() const { return (float)sqrtf(x * x + y * y + z * z); } +float Vector3::magnitude() const { + return (float)sqrtf(x * x + y * y + z * z); +} -float Vector3::SqrMagnitude(const Vector3 &v) { +float Vector3::SqrMagnitude(const Vector3& v) { return v.x * v.x + v.y * v.y + v.z * v.z; } -float Vector3::sqrMagnitude() const { return (x * x + y * y + z * z); } +float Vector3::sqrMagnitude() const { + return (x * x + y * y + z * z); +} -Vector3 Vector3::Normalize(const Vector3 &v) { +Vector3 Vector3::Normalize(const Vector3& v) { float num = Vector3::Magnitude(v); Vector3 result = Vector3::zero; if (num > epsilon) { @@ -96,46 +100,46 @@ Vector3 Vector3::operator-() const { return Vector3(-this->x, -this->y, -this->z); } -Vector3 Vector3::operator-(const Vector3 &v) const { +Vector3 Vector3::operator-(const Vector3& v) const { return Vector3(this->x - v.x, this->y - v.y, this->z - v.z); } -Vector3 Vector3::operator-=(const Vector3 &v) { +Vector3 Vector3::operator-=(const Vector3& v) { this->x -= v.x; this->y -= v.y; this->z -= v.z; return *this; } -Vector3 Vector3::operator+(const Vector3 &v) const { +Vector3 Vector3::operator+(const Vector3& v) const { return Vector3(this->x + v.x, this->y + v.y, this->z + v.z); } -Vector3 Vector3::operator+=(const Vector3 &v) { +Vector3 Vector3::operator+=(const Vector3& v) { this->x += v.x; this->y += v.y; this->z += v.z; return *this; } -Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) { +Vector3 Vector3::Scale(const Vector3& v1, const Vector3& v2) { return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } -Vector3 Passer::LinearAlgebra::operator*(const Vector3 &v, float f) { - return Vector3(v.x * f, v.y * f, v.z * f); -} -Vector3 Passer::LinearAlgebra::operator*(float f, const Vector3 &v) { - return Vector3(v.x * f, v.y * f, v.z * f); -} +// Vector3 Passer::LinearAlgebra::operator*(const Vector3 &v, float f) { +// return Vector3(v.x * f, v.y * f, v.z * f); +// } +// Vector3 Passer::LinearAlgebra::operator*(float f, const Vector3 &v) { +// return Vector3(v.x * f, v.y * f, v.z * f); +// } Vector3 Vector3::operator*=(float f) { this->x *= f; this->y *= f; this->z *= f; return *this; } -Vector3 Passer::LinearAlgebra::operator/(const Vector3 &v, float f) { - return Vector3(v.x / f, v.y / f, v.z / f); -} -Vector3 Passer::LinearAlgebra::operator/(float f, const Vector3 &v) { - return Vector3(v.x / f, v.y / f, v.z / f); -} +// Vector3 Passer::LinearAlgebra::operator/(const Vector3 &v, float f) { +// return Vector3(v.x / f, v.y / f, v.z / f); +// } +// Vector3 Passer::LinearAlgebra::operator/(float f, const Vector3 &v) { +// return Vector3(v.x / f, v.y / f, v.z / f); +// } Vector3 Vector3::operator/=(float f) { this->x /= f; this->y /= f; @@ -143,24 +147,24 @@ Vector3 Vector3::operator/=(float f) { return *this; } -float Vector3::Dot(const Vector3 &v1, const Vector3 &v2) { +float Vector3::Dot(const Vector3& v1, const Vector3& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } -bool Vector3::operator==(const Vector3 &v) { +bool Vector3::operator==(const Vector3& v) { return (this->x == v.x && this->y == v.y && this->z == v.z); } -float Vector3::Distance(const Vector3 &v1, const Vector3 &v2) { +float Vector3::Distance(const Vector3& v1, const Vector3& v2) { return Magnitude(v1 - v2); } -Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) { +Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2) { return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } -Vector3 Vector3::Project(const Vector3 &v, const Vector3 &n) { +Vector3 Vector3::Project(const Vector3& v, const Vector3& n) { float sqrMagnitude = Dot(n, n); if (sqrMagnitude < epsilon) return Vector3::zero; @@ -171,7 +175,7 @@ Vector3 Vector3::Project(const Vector3 &v, const Vector3 &n) { } } -Vector3 Vector3::ProjectOnPlane(const Vector3 &v, const Vector3 &n) { +Vector3 Vector3::ProjectOnPlane(const Vector3& v, const Vector3& n) { Vector3 r = v - Project(v, n); return r; } @@ -182,7 +186,7 @@ float clamp(float x, float lower, float upper) { return upperClamp; } -float Vector3::Angle(const Vector3 &v1, const Vector3 &v2) { +float Vector3::Angle(const Vector3& v1, const Vector3& v2) { float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude()); if (denominator < epsilon) return 0; @@ -190,15 +194,16 @@ float Vector3::Angle(const Vector3 &v1, const Vector3 &v2) { float dot = Vector3::Dot(v1, v2); float fraction = dot / denominator; if (isnan(fraction)) - return fraction; // short cut to returning NaN universally + return fraction; // short cut to returning NaN universally float cdot = clamp(fraction, -1.0, 1.0); float r = ((float)acos(cdot)) * Rad2Deg; return r; } -float Vector3::SignedAngle(const Vector3 &v1, const Vector3 &v2, - const Vector3 &axis) { +float Vector3::SignedAngle(const Vector3& v1, + const Vector3& v2, + const Vector3& axis) { // angle in [0,180] float angle = Vector3::Angle(v1, v2); @@ -212,7 +217,7 @@ float Vector3::SignedAngle(const Vector3 &v1, const Vector3 &v2, return signed_angle; } -Vector3 Vector3::Lerp(const Vector3 &v1, const Vector3 &v2, float f) { +Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) { Vector3 v = v1 + (v2 - v1) * f; return v; } diff --git a/Vector3.h b/Vector3.h index 27db549..f17eae8 100644 --- a/Vector3.h +++ b/Vector3.h @@ -19,7 +19,7 @@ extern "C" { /// This is a C-style implementation /// This uses the right-handed coordinate system. typedef struct Vec3 { -protected: + protected: /// /// The right axis of the vector /// @@ -42,7 +42,7 @@ protected: struct Vector3 : Vec3 { friend struct Vec3; -public: + public: /// @brief A new 3-dimensional zero vector Vector3(); /// @brief A new 3-dimensional vector @@ -88,12 +88,12 @@ public: /// @return true if it is identical to the given vector /// @note This uses float comparison to check equality which may have strange /// effects. Equality on floats should be avoided. - bool operator==(const Vector3 &v); + bool operator==(const Vector3& v); /// @brief The vector length /// @param v The vector for which you need the length /// @return The vector length - static float Magnitude(const Vector3 &v); + static float Magnitude(const Vector3& v); /// @brief The vector length /// @return The vector length float magnitude() const; @@ -103,7 +103,7 @@ public: /// @remark The squared length is computationally simpler than the real /// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the /// calculation of the squared root of C. - static float SqrMagnitude(const Vector3 &v); + static float SqrMagnitude(const Vector3& v); /// @brief The squared vector length /// @return The squared vector length /// @remark The squared length is computationally simpler than the real @@ -114,7 +114,7 @@ public: /// @brief Convert the vector to a length of 1 /// @param v The vector to convert /// @return The vector normalized to a length of 1 - static Vector3 Normalize(const Vector3 &v); + static Vector3 Normalize(const Vector3& v); /// @brief Convert the vector to a length of 1 /// @return The vector normalized to a length of 1 Vector3 normalized() const; @@ -126,13 +126,13 @@ public: /// @brief Subtract a vector from this vector /// @param v The vector to subtract from this vector /// @return The result of this subtraction - Vector3 operator-(const Vector3 &v) const; - Vector3 operator-=(const Vector3 &v); + Vector3 operator-(const Vector3& v) const; + Vector3 operator-=(const Vector3& v); /// @brief Add a vector to this vector /// @param v The vector to add to this vector /// @return The result of the addition - Vector3 operator+(const Vector3 &v) const; - Vector3 operator+=(const Vector3 &v); + Vector3 operator+(const Vector3& v) const; + Vector3 operator+=(const Vector3& v); /// @brief Scale the vector using another vector /// @param v1 The vector to scale @@ -140,52 +140,62 @@ public: /// @return The scaled vector /// @remark Each component of the vector v1 will be multiplied with the /// matching component from the scaling vector v2. - static Vector3 Scale(const Vector3 &v1, const Vector3 &v2); + static Vector3 Scale(const Vector3& v1, const Vector3& v2); /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - friend Vector3 operator*(const Vector3 &v, float f); - friend Vector3 operator*(float f, const Vector3 &v); + friend Vector3 operator*(const Vector3& v, float f) { + return Vector3(v.x * f, v.y * f, v.z * f); + } + friend Vector3 operator*(float f, const Vector3& v) { + // return Vector3(f * v.x, f * v.y, f * v.z); + return Vector3(v.x * f, v.y * f, v.z * f); + } Vector3 operator*=(float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - friend Vector3 operator/(const Vector3 &v, float f); - friend Vector3 operator/(float f, const Vector3 &v); + friend Vector3 operator/(const Vector3& v, float f) { + return Vector3(v.x / f, v.y / f, v.z / f); + } + friend Vector3 operator/(float f, const Vector3& v) { + // return Vector3(f / v.x, f / v.y, f / v.z); + return Vector3(v.x / f, v.y / f, v.z / f); + } Vector3 operator/=(float f); /// @brief The distance between two vectors /// @param v1 The first vector /// @param v2 The second vector /// @return The distance between the two vectors - static float Distance(const Vector3 &v1, const Vector3 &v2); + static float Distance(const Vector3& v1, const Vector3& v2); /// @brief The dot product of two vectors /// @param v1 The first vector /// @param v2 The second vector /// @return The dot product of the two vectors - static float Dot(const Vector3 &v1, const Vector3 &v2); + static float Dot(const Vector3& v1, const Vector3& v2); /// @brief The cross product of two vectors /// @param v1 The first vector /// @param v2 The second vector /// @return The cross product of the two vectors - static Vector3 Cross(const Vector3 &v1, const Vector3 &v2); + static Vector3 Cross(const Vector3& v1, const Vector3& v2); /// @brief Project the vector on another vector /// @param v The vector to project /// @param n The normal vecto to project on /// @return The projected vector - static Vector3 Project(const Vector3 &v, const Vector3 &n); + static Vector3 Project(const Vector3& v, const Vector3& n); /// @brief Project the vector on a plane defined by a normal orthogonal to the /// plane. /// @param v The vector to project /// @param n The normal of the plane to project on /// @return Teh projected vector - static Vector3 ProjectOnPlane(const Vector3 &v, const Vector3 &n); + static Vector3 ProjectOnPlane(const Vector3& v, const Vector3& n); /// @brief The angle between two vectors /// @param v1 The first vector @@ -194,14 +204,15 @@ public: /// @remark This reterns an unsigned angle which is the shortest distance /// between the two vectors. Use Vector3::SignedAngle if a signed angle is /// needed. - static float Angle(const Vector3 &v1, const Vector3 &v2); + static float Angle(const Vector3& v1, const Vector3& v2); /// @brief The signed angle between two vectors /// @param v1 The starting vector /// @param v2 The ending vector /// @param axis The axis to rotate around /// @return The signed angle between the two vectors - static float SignedAngle(const Vector3 &v1, const Vector3 &v2, - const Vector3 &axis); + static float SignedAngle(const Vector3& v1, + const Vector3& v2, + const Vector3& axis); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector @@ -211,11 +222,11 @@ public: /// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value /// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference /// between *v1* and *v2* etc. - static Vector3 Lerp(const Vector3 &v1, const Vector3 &v2, float f); + static Vector3 Lerp(const Vector3& v1, const Vector3& v2, float f); }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #include "Spherical.h" From a4b0491c2fe38d46cae16a1d2ef11e8fc965c40a Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 2 Aug 2024 11:27:16 +0200 Subject: [PATCH 058/121] Fix unit tests --- CMakeLists.txt | 2 ++ Vector2.h | 8 ++++++-- test/DiscreteAngle_test.cc | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0bcd5b..e25fb7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,8 @@ else() add_library(LinearAlgebra STATIC "FloatSingle.cpp" "Angle.cpp" + "Angle8.cpp" + "Angle16.cpp" "Vector2.cpp" "Vector3.cpp" "Quaternion.cpp" diff --git a/Vector2.h b/Vector2.h index 97d6c79..c4abf6c 100644 --- a/Vector2.h +++ b/Vector2.h @@ -150,8 +150,12 @@ struct Vector2 : Vec2 { /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - friend Vector2 operator/(const Vector2& v, float f); - friend Vector2 operator/(float f, const Vector2& v); + friend Vector2 operator/(const Vector2& v, float f) { + return Vector2(v.x / f, v.y / f); + } + friend Vector2 operator/(float f, const Vector2& v) { + return Vector2(f / v.x, f / v.y); + } Vector2 operator/=(float f); /// @brief The dot product of two vectors diff --git a/test/DiscreteAngle_test.cc b/test/DiscreteAngle_test.cc index b0d59df..510cbfa 100644 --- a/test/DiscreteAngle_test.cc +++ b/test/DiscreteAngle_test.cc @@ -1,8 +1,8 @@ #if GTEST #include -#include #include +#include #include "Angle16.h" #include "Angle8.h" @@ -12,12 +12,12 @@ TEST(Angle8, Construct) { float angle = 0.0F; Angle8 a = Angle8(angle); - float f = a.ToFloat(); + float f = (float)a; EXPECT_FLOAT_EQ(f, angle); angle = -180.0F; a = Angle8(angle); - f = a.ToFloat(); + f = (float)a; EXPECT_FLOAT_EQ(f, angle); } @@ -25,26 +25,26 @@ TEST(Angle8, Negate) { float angle = 0; Angle8 a = Angle8(angle); a = -a; - float f = a.ToFloat(); + float f = (float)a; EXPECT_FLOAT_EQ(f, angle); angle = 90.0F; a = Angle8(angle); a = -a; - f = a.ToFloat(); + f = (float)a; EXPECT_FLOAT_EQ(f, -angle); } TEST(Angle8, Add) { - Angle8 a = Angle8(0.0F); + Angle8 a = Angle8::Degrees(0.0F); Angle8 b = Angle8(0.0F); Angle8 r = a + b; - EXPECT_FLOAT_EQ(r.ToFloat(), 0); + EXPECT_FLOAT_EQ((float)r, 0); } TEST(Angle16, Construct) { Angle16 a = Angle16(0.0F); - float f = a.ToFloat(); + float f = (float)a; EXPECT_FLOAT_EQ(f, 0); } @@ -52,13 +52,13 @@ TEST(Angle16, Negate) { float angle = 0; Angle16 a = Angle16(angle); a = -a; - float f = a.ToFloat(); + float f = (float)a; EXPECT_FLOAT_EQ(f, angle); angle = 90.0F; a = Angle16(angle); a = -a; - f = a.ToFloat(); + f = (float)a; EXPECT_FLOAT_EQ(f, -angle); } #endif \ No newline at end of file From 86b7c21dca9861466439e2927a27a350d028c86f Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 2 Aug 2024 11:27:39 +0200 Subject: [PATCH 059/121] Added Degrees inline function --- Angle.h | 3 +++ Angle16.cpp | 17 +---------------- Angle16.h | 4 ++++ Angle8.h | 5 +++++ 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Angle.h b/Angle.h index 8be0583..b0259eb 100644 --- a/Angle.h +++ b/Angle.h @@ -16,6 +16,9 @@ class AngleOf { // AngleOf(T v) : value(v) {} // operator T() const; // { return value; } operator float() const; + + static AngleOf Degrees(float f); + inline T GetBinary() const { return this->value; } static AngleOf Rad2Deg; diff --git a/Angle16.cpp b/Angle16.cpp index d30e208..22d6748 100644 --- a/Angle16.cpp +++ b/Angle16.cpp @@ -13,7 +13,7 @@ AngleOf::AngleOf(float angle) { } // map float [-180..180) to integer [-32768..32767] - this->value = (signed short)((angle / 360.0F) * 65536.0F); + this->value = (signed short)(angle / 360.0F * 65536.0F); } template <> @@ -22,21 +22,6 @@ AngleOf::operator float() const { return f; } -// This should not exist... -// template <> -// AngleOf AngleOf::pi = 3.1415927410125732421875F; - -// template <> -// AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); -// template <> -// AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; - -// template <> -// AngleOf AngleOf::Normalize( -// AngleOf angle) { -// return angle; -// } - // Not correct!!! just for syntactical compilation ATM template <> AngleOf AngleOf::CosineRuleSide( diff --git a/Angle16.h b/Angle16.h index c3f55e9..8f7dbda 100644 --- a/Angle16.h +++ b/Angle16.h @@ -8,6 +8,10 @@ namespace LinearAlgebra { typedef AngleOf Angle16; +template <> +inline static Angle16 Angle16::Degrees(float angle) { + return (angle / 360.0F * 65536.0F); +} // template <> Angle16::AngleOf(float angle) { // if (!isfinite(angle)) { // value = 0; diff --git a/Angle8.h b/Angle8.h index 580c0af..d2bba64 100644 --- a/Angle8.h +++ b/Angle8.h @@ -8,6 +8,11 @@ namespace LinearAlgebra { typedef AngleOf Angle8; +template <> +inline static Angle8 Angle8::Degrees(float angle) { + return (angle / 360.0F * 256.0F); +} + // template <> Angle8::AngleOf(float angle) { // if (!isfinite(angle)) { // value = 0; From 48828e20b362d4272e406e833095d3d498f3192e Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 2 Aug 2024 11:55:27 +0200 Subject: [PATCH 060/121] Fix int/float issues --- Angle.cpp | 13 ++- Angle.h | 5 +- Angle16.cpp | 17 +++- Angle16.h | 16 ++- Angle8.cpp | 6 ++ Angle8.h | 8 +- Axis.cpp | 16 +-- CMakeLists.txt | 1 + Spherical.cpp | 2 +- test/Angle_test.cc | 200 ++++++++++++++++++------------------- test/DiscreteAngle_test.cc | 2 +- 11 files changed, 154 insertions(+), 132 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 4e69f45..6719140 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -73,6 +73,9 @@ float Angle::SineRuleAngle(float a, float beta, float b) { */ //---------------------- +template <> +AngleOf::AngleOf(int angle) : value(angle) {} + template <> AngleOf::AngleOf(float angle) : value(angle) {} @@ -127,8 +130,8 @@ AngleOf AngleOf::MoveTowards(AngleOf fromAngle, AngleOf toAngle, AngleOf maxAngle) { float d = toAngle - fromAngle; - float sign = signbit(d) ? -1 : 1; - d = sign * Float::Clamp(fabs(d), 0, maxAngle); + int sign = signbit(d) ? -1 : 1; + d = sign * Float::Clamp(fabsf(d), 0, maxAngle); return fromAngle + d; } @@ -141,7 +144,7 @@ AngleOf AngleOf::CosineRuleSide(float a, float d = a2 + b2 - 2 * a * b * cos(gamma * AngleOf::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) - return 0; + return 0.0f; float c = sqrtf(d); return c; @@ -155,9 +158,9 @@ AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { float d = (a2 + b2 - c2) / (2 * a * b); // Catch edge cases where float inacuracies lead tot nans if (d >= 1) - return 0; + return 0.0f; if (d <= -1) - return 180; + return 180.0f; float gamma = acos(d) * Angle::Rad2Deg; return gamma; diff --git a/Angle.h b/Angle.h index b0259eb..5b881da 100644 --- a/Angle.h +++ b/Angle.h @@ -12,13 +12,10 @@ template class AngleOf { public: AngleOf() {}; + AngleOf(int f); AngleOf(float f); - // AngleOf(T v) : value(v) {} - // operator T() const; // { return value; } operator float() const; - static AngleOf Degrees(float f); - inline T GetBinary() const { return this->value; } static AngleOf Rad2Deg; diff --git a/Angle16.cpp b/Angle16.cpp index 22d6748..2ac4210 100644 --- a/Angle16.cpp +++ b/Angle16.cpp @@ -3,8 +3,15 @@ // file, You can obtain one at https ://mozilla.org/MPL/2.0/. #include +#include #include "Angle.h" +template <> +AngleOf::AngleOf(int angle) { + signed long long_angle = (signed short)angle * 65535; + this->value = (signed short)(long_angle / 360); +} + template <> AngleOf::AngleOf(float angle) { if (!isfinite(angle)) { @@ -30,10 +37,10 @@ AngleOf AngleOf::CosineRuleSide( AngleOf gamma) { float a2 = a * a; float b2 = b * b; - float d = a2 + b2 - 2 * a * b * cos(gamma * AngleOf::Deg2Rad); + float d = a2 + b2 - 2 * a * b * cosf(gamma * AngleOf::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) - return 0; + return 0.0f; float c = sqrtf(d); return c; @@ -50,10 +57,10 @@ AngleOf AngleOf::CosineRuleAngle(float a, float d = (a2 + b2 - c2) / (2 * a * b); // Catch edge cases where float inacuracies lead tot nans if (d >= 1) - return 0; + return 0.0f; if (d <= -1) - return 180; + return 180.0f; - float gamma = acos(d) * Angle::Rad2Deg; + float gamma = acosf(d) * Angle::Rad2Deg; return gamma; } diff --git a/Angle16.h b/Angle16.h index 8f7dbda..c60a764 100644 --- a/Angle16.h +++ b/Angle16.h @@ -1,6 +1,7 @@ // #include "AngleUsing.h" #include +#include #include "Angle.h" namespace Passer { @@ -8,10 +9,17 @@ namespace LinearAlgebra { typedef AngleOf Angle16; -template <> -inline static Angle16 Angle16::Degrees(float angle) { - return (angle / 360.0F * 65536.0F); -} +// template <> +// inline static Angle16 Angle16::Degrees(short angle) { +// long long_angle = angle * 65535; +// long_angle = div(long_angle, (long)360); +// return Angle16(long_angle); //(long_angle / 360); +// } + +// template <> +// inline static Angle16 Angle16::Degrees(float angle) { +// return (angle / 360.0F * 65536.0F); +// } // template <> Angle16::AngleOf(float angle) { // if (!isfinite(angle)) { // value = 0; diff --git a/Angle8.cpp b/Angle8.cpp index a992466..fec8e30 100644 --- a/Angle8.cpp +++ b/Angle8.cpp @@ -5,6 +5,12 @@ #include #include "Angle.h" +template <> +AngleOf::AngleOf(int angle) { + signed short short_angle = (signed char)angle * 256; + this->value = (signed char)(short_angle / 360); +} + template <> AngleOf::AngleOf(float angle) { if (!isfinite(angle)) { diff --git a/Angle8.h b/Angle8.h index d2bba64..c3cea33 100644 --- a/Angle8.h +++ b/Angle8.h @@ -8,10 +8,10 @@ namespace LinearAlgebra { typedef AngleOf Angle8; -template <> -inline static Angle8 Angle8::Degrees(float angle) { - return (angle / 360.0F * 256.0F); -} +// template <> +// inline static Angle8 Angle8::Degrees(float angle) { +// return (angle / 360.0F * 256.0F); +// } // template <> Angle8::AngleOf(float angle) { // if (!isfinite(angle)) { diff --git a/Axis.cpp b/Axis.cpp index 2fba93e..6c7629c 100644 --- a/Axis.cpp +++ b/Axis.cpp @@ -10,8 +10,8 @@ #include Axis::Axis() { - horizontalAngle = 0; - verticalAngle = 0; + horizontalAngle = 0.0f; + verticalAngle = 0.0f; } Axis::Axis(Angle horizontal, Angle vertical) { @@ -24,12 +24,12 @@ Axis::Axis(Vector3 v) { this->verticalAngle = 90 - acosf(v.Up()) * Angle::Rad2Deg; } -const Axis Axis::forward = Axis(0, 0); -const Axis Axis::back = Axis(180, 0); -const Axis Axis::up = Axis(0, 90); -const Axis Axis::down = Axis(0, -90); -const Axis Axis::left = Axis(-90, 0); -const Axis Axis::right = Axis(90, 0); +const Axis Axis::forward = Axis(0.0f, 0.0f); +const Axis Axis::back = Axis(180.0f, 0.0f); +const Axis Axis::up = Axis(0.0f, 90.0f); +const Axis Axis::down = Axis(0.0f, -90.0f); +const Axis Axis::left = Axis(-90.0f, 0.0f); +const Axis Axis::right = Axis(90.0f, 0.0f); Vector3 Axis::ToVector3() { Vector3 v = diff --git a/CMakeLists.txt b/CMakeLists.txt index e25fb7a..bfa76be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ else() include(FetchContent) FetchContent_Declare( googletest + DOWNLOAD_EXTRACT_TIMESTAMP URL https://github.com/google/googletest/archive/refs/heads/main.zip ) diff --git a/Spherical.cpp b/Spherical.cpp index 860b621..ed97484 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -190,7 +190,7 @@ Angle Spherical::AngleBetween(const Spherical& v1, const Spherical& v2) { v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * // v2.distance * v2.distance); if (denominator < epsilon) - return 0; + return 0.0f; Vector3 v1_3 = Vector3(v1); Vector3 v2_3 = Vector3(v2); diff --git a/test/Angle_test.cc b/test/Angle_test.cc index 77ec3b6..21b4dce 100644 --- a/test/Angle_test.cc +++ b/test/Angle_test.cc @@ -9,159 +9,159 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() TEST(Angle, Normalize) { - float r = 0; + float r = 0; - r = Angle::Normalize(90); - EXPECT_FLOAT_EQ(r, 90) << "Normalize 90"; + r = Angle::Normalize(90.0f); + EXPECT_FLOAT_EQ(r, 90) << "Normalize 90"; - r = Angle::Normalize(-90); - EXPECT_FLOAT_EQ(r, -90) << "Normalize -90"; + r = Angle::Normalize(-90); + EXPECT_FLOAT_EQ(r, -90) << "Normalize -90"; - r = Angle::Normalize(270); - EXPECT_FLOAT_EQ(r, -90) << "Normalize 270"; + r = Angle::Normalize(270); + EXPECT_FLOAT_EQ(r, -90) << "Normalize 270"; - r = Angle::Normalize(270+360); - EXPECT_FLOAT_EQ(r, -90) << "Normalize 270+360"; + r = Angle::Normalize(270 + 360); + EXPECT_FLOAT_EQ(r, -90) << "Normalize 270+360"; - r = Angle::Normalize(-270); - EXPECT_FLOAT_EQ(r, 90) << "Normalize -270"; + r = Angle::Normalize(-270); + EXPECT_FLOAT_EQ(r, 90) << "Normalize -270"; - r = Angle::Normalize(-270 - 360); - EXPECT_FLOAT_EQ(r, 90) << "Normalize -270-360"; + r = Angle::Normalize(-270 - 360); + EXPECT_FLOAT_EQ(r, 90) << "Normalize -270-360"; - r = Angle::Normalize(0); - EXPECT_FLOAT_EQ(r, 0) << "Normalize 0"; + r = Angle::Normalize(0); + EXPECT_FLOAT_EQ(r, 0) << "Normalize 0"; - if (std::numeric_limits::is_iec559) { - r = Angle::Normalize(FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, FLOAT_INFINITY) << "Normalize INFINITY"; + if (std::numeric_limits::is_iec559) { + r = Angle::Normalize(FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r, FLOAT_INFINITY) << "Normalize INFINITY"; - r = Angle::Normalize(-FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, -FLOAT_INFINITY) << "Normalize INFINITY"; - } + r = Angle::Normalize(-FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r, -FLOAT_INFINITY) << "Normalize INFINITY"; + } } TEST(Angle, Clamp) { - float r = 0; + float r = 0; - r = Angle::Clamp(1, 0, 2); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 2"; + r = Angle::Clamp(1, 0, 2); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 2"; - r = Angle::Clamp(-1, 0, 2); - EXPECT_FLOAT_EQ(r, 0) << "Clamp -1 0 2"; + r = Angle::Clamp(-1, 0, 2); + EXPECT_FLOAT_EQ(r, 0) << "Clamp -1 0 2"; - r = Angle::Clamp(3, 0, 2); - EXPECT_FLOAT_EQ(r, 2) << "Clamp 3 0 2"; + r = Angle::Clamp(3, 0, 2); + EXPECT_FLOAT_EQ(r, 2) << "Clamp 3 0 2"; - r = Angle::Clamp(1, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Clamp 1 0 0"; + r = Angle::Clamp(1, 0, 0); + EXPECT_FLOAT_EQ(r, 0) << "Clamp 1 0 0"; - r = Angle::Clamp(0, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 0 0"; + r = Angle::Clamp(0, 0, 0); + EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 0 0"; - r = Angle::Clamp(0, 1, -1); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 0 1 -1"; + r = Angle::Clamp(0, 1, -1); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 0 1 -1"; - if (std::numeric_limits::is_iec559) { - r = Angle::Clamp(1, 0, FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 INFINITY"; + if (std::numeric_limits::is_iec559) { + r = Angle::Clamp(1, 0, FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 INFINITY"; - r = Angle::Clamp(1, -FLOAT_INFINITY, 1); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 -INFINITY 1"; - } + r = Angle::Clamp(1, -FLOAT_INFINITY, 1); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 -INFINITY 1"; + } } TEST(Angle, Difference) { - float r = 0; + float r = 0; - r = Angle::Difference(0, 90); - EXPECT_FLOAT_EQ(r, 90) << "Difference 0 90"; + r = Angle::Difference(0, 90); + EXPECT_FLOAT_EQ(r, 90) << "Difference 0 90"; - r = Angle::Difference(0, -90); - EXPECT_FLOAT_EQ(r, -90) << "Difference 0 -90"; + r = Angle::Difference(0, -90); + EXPECT_FLOAT_EQ(r, -90) << "Difference 0 -90"; - r = Angle::Difference(0, 270); - EXPECT_FLOAT_EQ(r, -90) << "Difference 0 270"; + r = Angle::Difference(0, 270); + EXPECT_FLOAT_EQ(r, -90) << "Difference 0 270"; - r = Angle::Difference(0, -270); - EXPECT_FLOAT_EQ(r, 90) << "Difference 0 -270"; + r = Angle::Difference(0, -270); + EXPECT_FLOAT_EQ(r, 90) << "Difference 0 -270"; - r = Angle::Difference(90, 0); - EXPECT_FLOAT_EQ(r, -90) << "Difference 90 0"; + r = Angle::Difference(90, 0); + EXPECT_FLOAT_EQ(r, -90) << "Difference 90 0"; - r = Angle::Difference(-90, 0); - EXPECT_FLOAT_EQ(r, 90) << "Difference -90 0"; + r = Angle::Difference(-90, 0); + EXPECT_FLOAT_EQ(r, 90) << "Difference -90 0"; - r = Angle::Difference(0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Difference 0 0"; + r = Angle::Difference(0, 0); + EXPECT_FLOAT_EQ(r, 0) << "Difference 0 0"; - r = Angle::Difference(90, 90); - EXPECT_FLOAT_EQ(r, 0) << "Difference 90 90"; + r = Angle::Difference(90, 90); + EXPECT_FLOAT_EQ(r, 0) << "Difference 90 90"; - if (std::numeric_limits::is_iec559) { - r = Angle::Difference(0, INFINITY); - EXPECT_FLOAT_EQ(r, INFINITY) << "Difference 0 INFINITY"; + if (std::numeric_limits::is_iec559) { + r = Angle::Difference(0, INFINITY); + EXPECT_FLOAT_EQ(r, INFINITY) << "Difference 0 INFINITY"; - r = Angle::Difference(0, -INFINITY); - EXPECT_FLOAT_EQ(r, -INFINITY) << "Difference 0 -INFINITY"; + r = Angle::Difference(0, -INFINITY); + EXPECT_FLOAT_EQ(r, -INFINITY) << "Difference 0 -INFINITY"; - r = Angle::Difference(-INFINITY, INFINITY); - EXPECT_FLOAT_EQ(r, INFINITY) << "Difference -INFINITY INFINITY"; - } + r = Angle::Difference(-INFINITY, INFINITY); + EXPECT_FLOAT_EQ(r, INFINITY) << "Difference -INFINITY INFINITY"; + } } TEST(Angle, MoveTowards) { - float r = 0; + float r = 0; - r = Angle::MoveTowards(0, 90, 30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 90 30"; + r = Angle::MoveTowards(0, 90, 30); + EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 90 30"; - r = Angle::MoveTowards(0, 90, 90); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 90"; + r = Angle::MoveTowards(0, 90, 90); + EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 90"; - r = Angle::MoveTowards(0, 90, 180); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 180"; + r = Angle::MoveTowards(0, 90, 180); + EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 180"; - r = Angle::MoveTowards(0, 90, 270); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 270"; + r = Angle::MoveTowards(0, 90, 270); + EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 270"; - r = Angle::MoveTowards(0, 90, -30); - EXPECT_FLOAT_EQ(r, -30) << "MoveTowards 0 90 -30"; + r = Angle::MoveTowards(0, 90, -30); + EXPECT_FLOAT_EQ(r, -30) << "MoveTowards 0 90 -30"; - r = Angle::MoveTowards(0, -90, -30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 -90 -30"; + r = Angle::MoveTowards(0, -90, -30); + EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 -90 -30"; - r = Angle::MoveTowards(0, -90, -90); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 -90 -90"; + r = Angle::MoveTowards(0, -90, -90); + EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 -90 -90"; - r = Angle::MoveTowards(0, -90, -180); - EXPECT_FLOAT_EQ(r, 180) << "MoveTowards 0 -90 -180"; + r = Angle::MoveTowards(0, -90, -180); + EXPECT_FLOAT_EQ(r, 180) << "MoveTowards 0 -90 -180"; - r = Angle::MoveTowards(0, -90, -270); - EXPECT_FLOAT_EQ(r, 270) << "MoveTowards 0 -90 -270"; + r = Angle::MoveTowards(0, -90, -270); + EXPECT_FLOAT_EQ(r, 270) << "MoveTowards 0 -90 -270"; - r = Angle::MoveTowards(0, 90, 0); - EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 90 0"; + r = Angle::MoveTowards(0, 90, 0); + EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 90 0"; - r = Angle::MoveTowards(0, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 0 0"; + r = Angle::MoveTowards(0, 0, 0); + EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 0 0"; - r = Angle::MoveTowards(0, 0, 30); - EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 0 30"; + r = Angle::MoveTowards(0, 0, 30); + EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 0 30"; - if (std::numeric_limits::is_iec559) { - r = Angle::MoveTowards(0, 90, FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 FLOAT_INFINITY"; + if (std::numeric_limits::is_iec559) { + r = Angle::MoveTowards(0, 90, FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 FLOAT_INFINITY"; - r = Angle::MoveTowards(0, FLOAT_INFINITY, 30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 FLOAT_INFINITY 30"; + r = Angle::MoveTowards(0, FLOAT_INFINITY, 30); + EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 FLOAT_INFINITY 30"; - r = Angle::MoveTowards(0, -90, -FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, FLOAT_INFINITY) << "MoveTowards 0 -90 -FLOAT_INFINITY"; + r = Angle::MoveTowards(0, -90, -FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r, FLOAT_INFINITY) << "MoveTowards 0 -90 -FLOAT_INFINITY"; - r = Angle::MoveTowards(0, -FLOAT_INFINITY, -30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; - } + r = Angle::MoveTowards(0, -FLOAT_INFINITY, -30); + EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; + } } #endif \ No newline at end of file diff --git a/test/DiscreteAngle_test.cc b/test/DiscreteAngle_test.cc index 510cbfa..bc26450 100644 --- a/test/DiscreteAngle_test.cc +++ b/test/DiscreteAngle_test.cc @@ -36,7 +36,7 @@ TEST(Angle8, Negate) { } TEST(Angle8, Add) { - Angle8 a = Angle8::Degrees(0.0F); + Angle8 a = Angle8(0); Angle8 b = Angle8(0.0F); Angle8 r = a + b; EXPECT_FLOAT_EQ((float)r, 0); From 4591aef90172d6f04fcf70f8570959507179ed75 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 2 Aug 2024 12:55:15 +0200 Subject: [PATCH 061/121] Added Spherical16 --- CMakeLists.txt | 2 + Spherical16.cpp | 232 +++++++++++++++++++++++++++++++++++++++ Spherical16.h | 158 ++++++++++++++++++++++++++ test/Spherical16_test.cc | 160 +++++++++++++++++++++++++++ 4 files changed, 552 insertions(+) create mode 100644 Spherical16.cpp create mode 100644 Spherical16.h create mode 100644 test/Spherical16_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index bfa76be..2df11da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ else() "Quaternion.cpp" "Polar.cpp" "Spherical.cpp" + "Spherical16.cpp" "Matrix.cpp" "Axis.cpp" "AngleAxis.cpp" @@ -50,6 +51,7 @@ else() "test/Matrix_test.cc" "test/Polar_test.cc" "test/Spherical_test.cc" + "test/Spherical16_test.cc" "test/DiscreteAngle_test.cc" ) target_link_libraries( diff --git a/Spherical16.cpp b/Spherical16.cpp new file mode 100644 index 0000000..b0761fb --- /dev/null +++ b/Spherical16.cpp @@ -0,0 +1,232 @@ +#include "Spherical16.h" + +#include "Quaternion.h" +#include "Spherical.h" + +#include + +Spherical16::Spherical16() { + this->distance = 0.0f; + this->horizontalAngle = Angle16(0); + this->verticalAngle = Angle16(0); +} + +Spherical16::Spherical16(Polar polar) { + this->distance = polar.distance; + this->horizontalAngle = Angle16(polar.angle); + this->verticalAngle = Angle16(0); +} + +Spherical16::Spherical16(float distance, + Angle16 horizontalAngle, + Angle16 verticalAngle) { + if (distance < 0) { + this->distance = -distance; + this->horizontalAngle = horizontalAngle - Angle16(180); + this->verticalAngle = verticalAngle; + } else { + this->distance = distance; + this->horizontalAngle = horizontalAngle; + this->verticalAngle = verticalAngle; + } +} + +Spherical16::Spherical16(Vector3 v) { + this->distance = v.magnitude(); + if (distance == 0.0f) { + this->verticalAngle = 0.0f; + this->horizontalAngle = 0.0f; + } else { + this->verticalAngle = + (90.0f - acosf(v.Up() / this->distance) * Angle::Rad2Deg); + this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; + } +} + +const Spherical16 Spherical16::zero = Spherical16(0.0f, 0.0f, 0.0f); +const Spherical16 Spherical16::forward = Spherical16(1.0f, 0.0f, 0.0f); +const Spherical16 Spherical16::back = Spherical16(1.0f, 180.0f, 0.0f); +const Spherical16 Spherical16::right = Spherical16(1.0f, 90.0f, 0.0f); +const Spherical16 Spherical16::left = Spherical16(1.0f, -90.0f, 0.0f); +const Spherical16 Spherical16::up = Spherical16(1.0f, 0.0f, 90.0f); +const Spherical16 Spherical16::down = Spherical16(1.0f, 0.0f, -90.0f); + +bool Spherical16::operator==(const Spherical16& v) const { + return (this->distance == v.distance && + this->horizontalAngle == v.horizontalAngle && + this->verticalAngle == v.verticalAngle); +} + +Spherical16 Spherical16::Normalize(const Spherical16& v) { + Spherical16 r = Spherical16(1, v.horizontalAngle, v.verticalAngle); + return r; +} +Spherical16 Spherical16::normalized() const { + Spherical16 r = Spherical16(1, this->horizontalAngle, this->verticalAngle); + return r; +} + +Spherical16 Spherical16::operator-() const { + Spherical16 v = Spherical16(this->distance, this->horizontalAngle + 180.0f, + this->verticalAngle + 180.0f); + return v; +} + +Spherical16 Spherical16::operator-(const Spherical16& s2) const { + Spherical thisSpherical = Spherical( + this->distance, (Angle)this->horizontalAngle, (Angle)this->verticalAngle); + Spherical spherical2 = Spherical(s2.distance, (Angle)s2.horizontalAngle, + (Angle)s2.verticalAngle); + + // let's do it the easy way... + Vector3 v1 = Vector3(thisSpherical); + Vector3 v2 = Vector3(spherical2); + Vector3 v = v1 - v2; + Spherical16 r = Spherical16(v); + return r; +} +Spherical16 Spherical16::operator-=(const Spherical16& v) { + *this = *this - v; + return *this; +} + +Spherical16 Spherical16::operator+(const Spherical16& s2) const { + // let's do it the easy way... + Vector3 v1 = Vector3(Spherical(this->distance, (float)this->horizontalAngle, + (float)this->verticalAngle)); + Vector3 v2 = Vector3(Spherical(s2.distance, (float)s2.horizontalAngle, + (float)s2.verticalAngle)); + Vector3 v = v1 + v2; + Spherical16 r = Spherical16(v); + return r; + /* + // This is the hard way... + if (v2.distance <= 0) + return Spherical(this->distance, this->horizontalAngle, + this->verticalAngle); + if (this->distance <= 0) + return v2; + + float deltaHorizontalAngle = + (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); + float horizontalRotation = deltaHorizontalAngle < 0 + ? 180 + deltaHorizontalAngle + : 180 - deltaHorizontalAngle; + float deltaVerticalAngle = + Angle::Normalize(v2.verticalAngle - this->verticalAngle); + float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle + : 180 - deltaVerticalAngle; + + if (horizontalRotation == 180 && verticalRotation == 180) + // angle is too small, take this angle and add the distances + return Spherical(this->distance + v2.distance, this->horizontalAngle, + this->verticalAngle); + + Angle rotation = AngleBetween(*this, v2); + float newDistance = + Angle::CosineRuleSide(v2.distance, this->distance, rotation); + float angle = + Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); + + // Now we have to project the angle to the horizontal and vertical planes... + // The axis for the angle is the cross product of the two spherical vectors + // (which function we do not have either...) + float horizontalAngle = 0; + float verticalAngle = 0; + + float newHorizontalAngle = + deltaHorizontalAngle < 0 + ? Angle::Normalize(this->horizontalAngle - horizontalAngle) + : Angle::Normalize(this->horizontalAngle + horizontalAngle); + float newVerticalAngle = + deltaVerticalAngle < 0 + ? Angle::Normalize(this->verticalAngle - verticalAngle) + : Angle::Normalize(this->verticalAngle + verticalAngle); + + Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); + */ +} +Spherical16 Spherical16::operator+=(const Spherical16& v) { + *this = *this + v; + return *this; +} + +// Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { +// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); +// } +// Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) { +// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); +// } +Spherical16 Spherical16::operator*=(float f) { + this->distance *= f; + return *this; +} + +// Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { +// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); +// } +// Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) { +// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); +// } +Spherical16 Spherical16::operator/=(float f) { + this->distance /= f; + return *this; +} + +// float Spherical::GetSwing() { +// // Not sure if this is correct +// return sqrtf(horizontalAngle * horizontalAngle + +// verticalAngle * verticalAngle); +// } + +// float Spherical::Distance(const Spherical &s1, const Spherical &s2) { +// float d = 0; +// return d; +// } + +#include "AngleUsing.h" +#include "FloatSingle.h" +#include "Vector3.h" + +const float epsilon = 1E-05f; +const float Rad2Deg = 57.29578F; + +Angle Spherical16::AngleBetween(const Spherical16& v1, const Spherical16& v2) { + // float denominator = sqrtf(v1_3.sqrMagnitude() * v2_3.sqrMagnitude()); + float denominator = + v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * + // v2.distance * v2.distance); + if (denominator < epsilon) + return 0.0f; + + Vector3 v1_3 = Vector3(Spherical(v1.distance, (Angle)v1.horizontalAngle, + (Angle)v1.verticalAngle)); + Vector3 v2_3 = Vector3(Spherical(v2.distance, (Angle)v2.horizontalAngle, + (Angle)v2.verticalAngle)); + float dot = Vector3::Dot(v1_3, v2_3); + float fraction = dot / denominator; + if (isnan(fraction)) + return fraction; // short cut to returning NaN universally + + float cdot = Float::Clamp(fraction, -1.0, 1.0); + float r = ((float)acos(cdot)) * Rad2Deg; + return r; +} + +Spherical16 Spherical16::Rotate(const Spherical16& v, + Angle horizontalAngle, + Angle verticalAngle) { + Spherical16 r = Spherical16(v.distance, v.horizontalAngle + horizontalAngle, + v.verticalAngle + verticalAngle); + return r; +} +Spherical16 Spherical16::RotateHorizontal(const Spherical16& v, Angle a) { + Spherical16 r = + Spherical16(v.distance, v.horizontalAngle + a, v.verticalAngle); + return r; +} +Spherical16 Spherical16::RotateVertical(const Spherical16& v, Angle a) { + Spherical16 r = + Spherical16(v.distance, v.horizontalAngle, v.verticalAngle + a); + return r; +} \ No newline at end of file diff --git a/Spherical16.h b/Spherical16.h new file mode 100644 index 0000000..1f9f448 --- /dev/null +++ b/Spherical16.h @@ -0,0 +1,158 @@ +// 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/. + +#ifndef SPHERICAL16_H +#define SPHERICAL16_H + +#include "Angle16.h" +#include "Polar.h" + +namespace Passer { +namespace LinearAlgebra { + +struct Vector3; + +/// @brief A spherical vector +/// @details This is a vector in 3D space using a spherical coordinate system. +/// It consists of a distance and the polar and elevation angles from a +/// reference direction. The reference direction is typically thought of +/// as a forward direction. +/// In contrast to the normal Spherical type, this version uses 16 bit integers +/// for the angles +struct Spherical16 { + public: + /// @brief The distance in meters + /// @remark The distance should never be negative + float distance; + /// @brief The angle in the horizontal plane in degrees, clockwise rotation + /// @details The angle is automatically normalized to -180 .. 180 + Angle16 horizontalAngle; + /// @brief The angle in the vertical plane in degrees. Positive is upward. + /// @details The angle is automatically normalized to -180 .. 180 + Angle16 verticalAngle; + + /// @brief Create a new spherical vector with zero degrees and distance + Spherical16(); + /// @brief Create a new spherical vector + /// @param distance The distance in meters + /// @param horizontalAngle The angle in the horizontal plane in degrees, + /// clockwise rotation + /// @param verticalAngle The angle in the vertical plan in degrees, + /// zero is forward, positive is upward + Spherical16(float distance, Angle16 horizontalAngle, Angle16 verticalAngle); + /// @brief Convert polar coordinates to spherical coordinates + /// @param polar The polar coordinate + Spherical16(Polar polar); + /// @brief Convert 3D carthesian coordinates to spherical coordinates + /// @param v Vector in 3D carthesian coordinates; + Spherical16(Vector3 v); + + /// @brief A spherical vector with zero degree angles and distance + const static Spherical16 zero; + /// @brief A normalized forward-oriented vector + const static Spherical16 forward; + /// @brief A normalized back-oriented vector + const static Spherical16 back; + /// @brief A normalized right-oriented vector + const static Spherical16 right; + /// @brief A normalized left-oriented vector + const static Spherical16 left; + /// @brief A normalized up-oriented vector + const static Spherical16 up; + /// @brief A normalized down-oriented vector + const static Spherical16 down; + + /// @brief Equality test to another vector + /// @param v The vector to check against + /// @return true: if it is identical to the given vector + /// @note This uses float comparison to check equality which may have strange + /// effects. Equality on floats should be avoided. + bool operator==(const Spherical16& v) const; + + /// @brief The vector length + /// @param v The vector for which you need the length + /// @return The vector length; + inline static float Magnitude(const Spherical16& v) { return v.distance; } + /// @brief The vector length + /// @return The vector length + inline float magnitude() const { return this->distance; } + + /// @brief Convert the vector to a length of 1 + /// @param v The vector to convert + /// @return The vector normalized to a length of 1 + static Spherical16 Normalize(const Spherical16& v); + /// @brief Convert the vector to a length of a + /// @return The vector normalized to a length of 1 + Spherical16 normalized() const; + + /// @brief Negate the vector + /// @return The negated vector + /// This will rotate the vector by 180 degrees horizontally and + /// vertically. Distance will stay the same. + Spherical16 operator-() const; + + /// @brief Subtract a spherical vector from this vector + /// @param v The vector to subtract + /// @return The result of the subtraction + Spherical16 operator-(const Spherical16& v) const; + Spherical16 operator-=(const Spherical16& v); + /// @brief Add a spherical vector to this vector + /// @param v The vector to add + /// @return The result of the addition + Spherical16 operator+(const Spherical16& v) const; + Spherical16 operator+=(const Spherical16& v); + + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend Spherical16 operator*(const Spherical16& v, float f) { + return Spherical16(v.distance * f, v.horizontalAngle, v.verticalAngle); + } + friend Spherical16 operator*(float f, const Spherical16& v) { + return Spherical16( + v.distance * f, v.horizontalAngle, + v.verticalAngle); // not correct, should be f * v.distance + } + Spherical16 operator*=(float f); + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled factor + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend Spherical16 operator/(const Spherical16& v, float f) { + return Spherical16(v.distance / f, v.horizontalAngle, v.verticalAngle); + } + friend Spherical16 operator/(float f, const Spherical16& v) { + return Spherical16( + v.distance / f, v.horizontalAngle, + v.verticalAngle); // not correct, should be f / v.distance + } + Spherical16 operator/=(float f); + + /// + /// The distance between two vectors + /// + /// The first vector + /// The second vector + /// The distance between the two vectors + // static float Distance(const Spherical16 &s1, const Spherical16 &s2); + + static Angle AngleBetween(const Spherical16& v1, const Spherical16& v2); + + static Spherical16 Rotate(const Spherical16& v, + Angle horizontalAngle, + Angle verticalAngle); + static Spherical16 RotateHorizontal(const Spherical16& v, Angle angle); + static Spherical16 RotateVertical(const Spherical16& v, Angle angle); +}; + +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#include "Vector3.h" + +#endif \ No newline at end of file diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc new file mode 100644 index 0000000..3dfac4c --- /dev/null +++ b/test/Spherical16_test.cc @@ -0,0 +1,160 @@ +#if GTEST +#include +#include +#include + +#include "Spherical16.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Spherical16, FromVector3) { + Vector3 v = Vector3(0, 0, 1); + Spherical16 s = Spherical16(v); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; + EXPECT_FLOAT_EQ((float)s.horizontalAngle, 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ((float)s.verticalAngle, 0.0F) << "s.vert 0 0 1"; + + v = Vector3(0, 1, 0); + s = Spherical16(v); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.verticalAngle, 90.0F) << "s.vert 0 1 0"; + + v = Vector3(1, 0, 0); + s = Spherical16(v); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 1 0 0"; +} + +TEST(Spherical16, FromPolar) { + Polar p = Polar(1, 0); + Spherical16 s = Spherical16(p); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor Polar(1 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 0)"; + + p = Polar(1, 45); + s = Spherical16(p); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 45.0F) << "s.hor Polar(1 45)"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 45)"; + + p = Polar(1, -45); + s = Spherical16(p); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.horizontalAngle, -45.0F) << "s.hor Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 -45)"; + + p = Polar(0, 0); + s = Spherical16(p); + + EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor Polar(0 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(0 0)"; + + p = Polar(-1, 0); + s = Spherical16(p); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle, -180.0F) << "s.hor Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(-1 0)"; +} + +TEST(Spherical16, Incident1) { + Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); + Spherical16 s = Spherical16(v); + + Spherical16 sr = Spherical16(2.49F, 98.18f, 24.4F); + EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); + EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-02); + EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-02); + + Vector3 r = Vector3(Spherical(sr.distance, (Angle)sr.horizontalAngle, + (Angle)sr.verticalAngle)); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0"; +} + +TEST(Spherical16, Incident2) { + Vector3 v = Vector3(1.0f, 0.0f, 1.0f); + Spherical16 s = Spherical16(v); + + Spherical16 sr = Spherical16(1.4142135623F, 45.0f, 0.0F); + EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); + EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + + Vector3 r = Vector3(Spherical(sr.distance, (Angle)sr.horizontalAngle, + (Angle)sr.verticalAngle)); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); + + v = Vector3(0.0f, 1.0f, 1.0f); + s = Spherical16(v); + + sr = Spherical16(1.4142135623F, 0.0f, 45.0F); + EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); + EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + + r = Vector3(Spherical(sr.distance, (Angle)sr.horizontalAngle, + (Angle)sr.verticalAngle)); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); + + v = Vector3(1.0f, 1.0f, 1.0f); + s = Spherical16(v); + r = Vector3( + Spherical(s.distance, (Angle)s.horizontalAngle, (Angle)s.verticalAngle)); + + EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); + EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); + EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-02); + + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-04); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-04); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-04); + + // s = Spherical16(10, 45, 45); + // r = s.ToVector3(); + // EXPECT_NEAR(r.x, 5, 1.0e-06); + // EXPECT_NEAR(r.y, 7.07, 1.0e-06); + // EXPECT_NEAR(r.z, 5, 1.0e-06); +} + +TEST(Spherical16, Addition) { + Spherical16 v1 = Spherical16(1, 45, 0); + Spherical16 v2 = Spherical16::zero; + Spherical16 r = Spherical16::zero; + + r = v1 + v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; + + r = v1; + r += v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; + + v2 = Spherical16(1, -45, 0); + r = v1 + v2; + EXPECT_NEAR(r.distance, sqrtf(2), 1.0e-02) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontalAngle, 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.verticalAngle, 0) << "Addition(1 -45 0)"; + + v2 = Spherical16(1, 0, 90); + r = v1 + v2; + EXPECT_NEAR(r.distance, sqrtf(2), 1.0e-02) << "Addition(1 0 90)"; + EXPECT_NEAR(r.horizontalAngle, 45, 1.0e-01) << "Addition(1 0 90)"; + EXPECT_NEAR(r.verticalAngle, 45, 1.0e-02) << "Addition(1 0 90)"; +} + +#endif \ No newline at end of file From 608c45c1a7b7f5469cfdcd1a8ff30036111aefb2 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 2 Aug 2024 14:27:42 +0200 Subject: [PATCH 062/121] Fix precision error --- Angle16.cpp | 2 +- test/Spherical16_test.cc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Angle16.cpp b/Angle16.cpp index 2ac4210..c227779 100644 --- a/Angle16.cpp +++ b/Angle16.cpp @@ -8,7 +8,7 @@ template <> AngleOf::AngleOf(int angle) { - signed long long_angle = (signed short)angle * 65535; + signed long long_angle = (signed short)angle * 65536; this->value = (signed short)(long_angle / 360); } diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index 3dfac4c..318d845 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -146,15 +146,15 @@ TEST(Spherical16, Addition) { v2 = Spherical16(1, -45, 0); r = v1 + v2; - EXPECT_NEAR(r.distance, sqrtf(2), 1.0e-02) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.horizontalAngle, 0) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.verticalAngle, 0) << "Addition(1 -45 0)"; v2 = Spherical16(1, 0, 90); r = v1 + v2; - EXPECT_NEAR(r.distance, sqrtf(2), 1.0e-02) << "Addition(1 0 90)"; - EXPECT_NEAR(r.horizontalAngle, 45, 1.0e-01) << "Addition(1 0 90)"; - EXPECT_NEAR(r.verticalAngle, 45, 1.0e-02) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontalAngle, 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.verticalAngle, 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file From 49c67405fcbf15b3470080e67ab203c835f1f9b8 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 5 Aug 2024 10:03:42 +0200 Subject: [PATCH 063/121] Make Angle -> float conversion explicit --- Angle.cpp | 44 ++++++++++------- Angle.h | 11 ++++- Angle16.cpp | 13 +++-- Angle8.cpp | 8 +++- Axis.cpp | 11 +++-- Polar.cpp | 29 +++++++----- Spherical.cpp | 30 +++++++----- Spherical16.cpp | 59 ++++++++++++----------- Vector2.cpp | 6 +-- Vector3.cpp | 6 ++- test/Angle_test.cc | 97 +++++++++++++++++++------------------- test/DiscreteAngle_test.cc | 26 +++++----- test/Polar_test.cc | 34 ++++++------- test/Spherical16_test.cc | 75 +++++++++++++++-------------- test/Spherical_test.cc | 61 ++++++++++++------------ 15 files changed, 283 insertions(+), 227 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 6719140..3b0b3d5 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -74,32 +74,37 @@ float Angle::SineRuleAngle(float a, float beta, float b) { //---------------------- template <> -AngleOf::AngleOf(int angle) : value(angle) {} +AngleOf::AngleOf(int angle) : value((float)angle) {} template <> AngleOf::AngleOf(float angle) : value(angle) {} +// template <> +// AngleOf::operator float() const { +// return value; +// } + template <> -AngleOf::operator float() const { +float AngleOf::ToFloat() const { return value; } -template <> -AngleOf AngleOf::pi = 3.1415927410125732421875F; +// template <> +// AngleOf AngleOf::pi = 3.1415927410125732421875F; -template <> -AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); -template <> -AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; +// template <> +// AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); +// template <> +// AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; template <> bool Passer::LinearAlgebra::AngleOf::operator==(AngleOf a) { - return (float)*this == (float)a; + return this->ToFloat() == a.ToFloat(); } template <> AngleOf AngleOf::Normalize(AngleOf angle) { - float angleValue = angle; + float angleValue = angle.ToFloat(); if (!isfinite(angleValue)) return angleValue; @@ -114,8 +119,8 @@ template <> AngleOf AngleOf::Clamp(AngleOf angle, AngleOf min, AngleOf max) { - float normalizedAngle = Normalize(angle); - float r = Float::Clamp(normalizedAngle, min, max); + float normalizedAngle = Normalize(angle).ToFloat(); + float r = Float::Clamp(normalizedAngle, min.ToFloat(), max.ToFloat()); return r; } @@ -129,10 +134,10 @@ template <> AngleOf AngleOf::MoveTowards(AngleOf fromAngle, AngleOf toAngle, AngleOf maxAngle) { - float d = toAngle - fromAngle; + float d = toAngle.ToFloat() - fromAngle.ToFloat(); int sign = signbit(d) ? -1 : 1; - d = sign * Float::Clamp(fabsf(d), 0, maxAngle); - return fromAngle + d; + d = sign * Float::Clamp(fabsf(d), 0, maxAngle.ToFloat()); + return fromAngle.ToFloat() + d; } template <> @@ -141,7 +146,8 @@ AngleOf AngleOf::CosineRuleSide(float a, AngleOf gamma) { float a2 = a * a; float b2 = b * b; - float d = a2 + b2 - 2 * a * b * cos(gamma * AngleOf::Deg2Rad); + float d = a2 + b2 - + 2 * a * b * cosf(gamma.ToFloat() * Passer::LinearAlgebra::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) return 0.0f; @@ -162,7 +168,8 @@ AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { if (d <= -1) return 180.0f; - float gamma = acos(d) * Angle::Rad2Deg; + float rad2deg = Passer::LinearAlgebra::Rad2Deg; + float gamma = acosf(d) * rad2deg; return gamma; } @@ -170,6 +177,7 @@ template <> AngleOf AngleOf::SineRuleAngle(float a, AngleOf beta, float b) { - float alpha = asin(a * sin(beta * Angle::Deg2Rad) / b); + float deg2rad = Passer::LinearAlgebra::Deg2Rad; + float alpha = asinf(a * sinf(beta.ToFloat() * deg2rad) / b); return alpha; } \ No newline at end of file diff --git a/Angle.h b/Angle.h index 5b881da..fc845a8 100644 --- a/Angle.h +++ b/Angle.h @@ -8,13 +8,20 @@ namespace Passer { namespace LinearAlgebra { +static float pi = 3.1415927410125732421875F; + +static float Rad2Deg = 360.0f / (pi * 2); +static float Deg2Rad = (pi * 2) / 360.0f; + template class AngleOf { public: AngleOf() {}; AngleOf(int f); AngleOf(float f); - operator float() const; + // operator float() const; + + float ToFloat() const; inline T GetBinary() const { return this->value; } @@ -28,7 +35,7 @@ class AngleOf { static AngleOf Normalize(AngleOf a); static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); static AngleOf Difference(AngleOf a, AngleOf b) { - AngleOf r = Normalize(b - a); + AngleOf r = Normalize(b.ToFloat() - a.ToFloat()); return r; }; static AngleOf MoveTowards(AngleOf fromAngle, diff --git a/Angle16.cpp b/Angle16.cpp index c227779..e5e9cc5 100644 --- a/Angle16.cpp +++ b/Angle16.cpp @@ -23,8 +23,14 @@ AngleOf::AngleOf(float angle) { this->value = (signed short)(angle / 360.0F * 65536.0F); } +// template <> +// AngleOf::operator float() const { +// float f = ((this->value * 180) / 32768.0F); +// return f; +// } + template <> -AngleOf::operator float() const { +float AngleOf::ToFloat() const { float f = ((this->value * 180) / 32768.0F); return f; } @@ -37,7 +43,8 @@ AngleOf AngleOf::CosineRuleSide( AngleOf gamma) { float a2 = a * a; float b2 = b * b; - float d = a2 + b2 - 2 * a * b * cosf(gamma * AngleOf::Deg2Rad); + float d = a2 + b2 - + 2 * a * b * cosf(gamma.ToFloat() * Passer::LinearAlgebra::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) return 0.0f; @@ -61,6 +68,6 @@ AngleOf AngleOf::CosineRuleAngle(float a, if (d <= -1) return 180.0f; - float gamma = acosf(d) * Angle::Rad2Deg; + float gamma = acosf(d) * Passer::LinearAlgebra::Rad2Deg; return gamma; } diff --git a/Angle8.cpp b/Angle8.cpp index fec8e30..0ff2af0 100644 --- a/Angle8.cpp +++ b/Angle8.cpp @@ -23,8 +23,14 @@ AngleOf::AngleOf(float angle) { this->value = (signed char)(f * 256.0F); } +// template <> +// AngleOf::operator float() const { +// float f = (this->value * 180) / 128.0F; +// return f; +// } + template <> -AngleOf::operator float() const { +float AngleOf::ToFloat() const { float f = (this->value * 180) / 128.0F; return f; } diff --git a/Axis.cpp b/Axis.cpp index 6c7629c..02f9ebc 100644 --- a/Axis.cpp +++ b/Axis.cpp @@ -20,8 +20,9 @@ Axis::Axis(Angle horizontal, Angle vertical) { }; Axis::Axis(Vector3 v) { - this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; - this->verticalAngle = 90 - acosf(v.Up()) * Angle::Rad2Deg; + this->horizontalAngle = + atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; + this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; } const Axis Axis::forward = Axis(0.0f, 0.0f); @@ -32,8 +33,8 @@ const Axis Axis::left = Axis(-90.0f, 0.0f); const Axis Axis::right = Axis(90.0f, 0.0f); Vector3 Axis::ToVector3() { - Vector3 v = - Quaternion::Euler(-this->verticalAngle, this->horizontalAngle, 0) * - Vector3::forward; + Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), + this->horizontalAngle.ToFloat(), 0) * + Vector3::forward; return v; } \ No newline at end of file diff --git a/Polar.cpp b/Polar.cpp index 8bebaf1..b3f09e8 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -12,7 +12,7 @@ Polar::Polar(float distance, Angle angle) { // distance should always be 0 or greater if (distance < 0.0f) { this->distance = -distance; - this->angle = Angle::Normalize(angle - 180); + this->angle = Angle::Normalize(angle.ToFloat() - 180.0f); } else { this->distance = distance; if (this->distance == 0.0f) @@ -27,7 +27,8 @@ Polar::Polar(Vector2 v) { this->angle = Vector2::SignedAngle(Vector2::forward, v); } Polar::Polar(Spherical v) { - this->distance = v.distance * cosf(v.verticalAngle * Angle::Deg2Rad); + this->distance = v.distance * cosf(v.verticalAngle.ToFloat() * + Passer::LinearAlgebra::Deg2Rad); this->angle = v.horizontalAngle; } @@ -38,7 +39,8 @@ const Polar Polar::right = Polar(1.0, 90.0f); const Polar Polar::left = Polar(1.0, -90.0f); bool Polar::operator==(const Polar& v) const { - return (this->distance == v.distance && this->angle == v.angle); + return (this->distance == v.distance && + this->angle.ToFloat() == v.angle.ToFloat()); } Polar Polar::Normalize(const Polar& v) { @@ -51,7 +53,7 @@ Polar Polar::normalized() const { } Polar Polar::operator-() const { - Polar v = Polar(this->distance, this->angle + 180); + Polar v = Polar(this->distance, this->angle.ToFloat() + 180.0f); return v; } @@ -69,7 +71,8 @@ Polar Polar::operator+(const Polar& v) const { if (this->distance == 0.0f) return v; - float deltaAngle = Angle::Normalize(v.angle - (float)this->angle); + float deltaAngle = + Angle::Normalize(v.angle.ToFloat() - this->angle.ToFloat()).ToFloat(); float rotation = deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle; @@ -79,13 +82,14 @@ Polar Polar::operator+(const Polar& v) const { } float newDistance = - Angle::CosineRuleSide(v.distance, this->distance, rotation); + Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat(); - float angle = Angle::CosineRuleAngle(newDistance, this->distance, v.distance); + float angle = + Angle::CosineRuleAngle(newDistance, this->distance, v.distance).ToFloat(); - float newAngle = deltaAngle < 0.0f ? (float)this->angle - angle - : (float)this->angle + angle; - newAngle = Angle::Normalize(newAngle); + float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle + : this->angle.ToFloat() + angle; + newAngle = Angle::Normalize(newAngle).ToFloat(); Polar vector = Polar(newDistance, newAngle); return vector; } @@ -117,12 +121,13 @@ Polar Polar::operator/=(float f) { float Polar::Distance(const Polar& v1, const Polar& v2) { float d = Angle::CosineRuleSide(v1.distance, v2.distance, - (float)v2.angle - (float)v1.angle); + v2.angle.ToFloat() - v1.angle.ToFloat()) + .ToFloat(); return d; } Polar Polar::Rotate(const Polar& v, Angle angle) { - Angle a = Angle::Normalize(v.angle + angle); + Angle a = Angle::Normalize(v.angle.ToFloat() + angle.ToFloat()); Polar r = Polar(v.distance, a); return r; } \ No newline at end of file diff --git a/Spherical.cpp b/Spherical.cpp index ed97484..f1a80d1 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -22,7 +22,8 @@ Spherical::Spherical(float distance, Angle verticalAngle) { if (distance < 0) { this->distance = -distance; - this->horizontalAngle = Angle::Normalize(horizontalAngle - 180); + this->horizontalAngle = + Angle::Normalize(horizontalAngle.ToFloat() - 180.0f); this->verticalAngle = verticalAngle; } else { this->distance = distance; @@ -37,9 +38,10 @@ Spherical::Spherical(Vector3 v) { this->verticalAngle = 0.0f; this->horizontalAngle = 0.0f; } else { - this->verticalAngle = - (90.0f - acosf(v.Up() / this->distance) * Angle::Rad2Deg); - this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; + this->verticalAngle = (90.0f - acosf(v.Up() / this->distance) * + Passer::LinearAlgebra::Rad2Deg); + this->horizontalAngle = + atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; } } @@ -53,8 +55,8 @@ const Spherical Spherical::down = Spherical(1.0f, 0.0f, -90.0f); bool Spherical::operator==(const Spherical& v) const { return (this->distance == v.distance && - this->horizontalAngle == v.horizontalAngle && - this->verticalAngle == v.verticalAngle); + this->horizontalAngle.ToFloat() == v.horizontalAngle.ToFloat() && + this->verticalAngle.ToFloat() == v.verticalAngle.ToFloat()); } Spherical Spherical::Normalize(const Spherical& v) { @@ -67,8 +69,9 @@ Spherical Spherical::normalized() const { } Spherical Spherical::operator-() const { - Spherical v = Spherical(this->distance, this->horizontalAngle + 180.0f, - this->verticalAngle + 180.0f); + Spherical v = + Spherical(this->distance, this->horizontalAngle.ToFloat() + 180.0f, + this->verticalAngle.ToFloat() + 180.0f); return v; } @@ -207,15 +210,18 @@ Angle Spherical::AngleBetween(const Spherical& v1, const Spherical& v2) { Spherical Spherical::Rotate(const Spherical& v, Angle horizontalAngle, Angle verticalAngle) { - Spherical r = Spherical(v.distance, v.horizontalAngle + horizontalAngle, - v.verticalAngle + verticalAngle); + Spherical r = Spherical( + v.distance, v.horizontalAngle.ToFloat() + horizontalAngle.ToFloat(), + v.verticalAngle.ToFloat() + verticalAngle.ToFloat()); return r; } Spherical Spherical::RotateHorizontal(const Spherical& v, Angle a) { - Spherical r = Spherical(v.distance, v.horizontalAngle + a, v.verticalAngle); + Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat() + a.ToFloat(), + v.verticalAngle.ToFloat()); return r; } Spherical Spherical::RotateVertical(const Spherical& v, Angle a) { - Spherical r = Spherical(v.distance, v.horizontalAngle, v.verticalAngle + a); + Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat(), + v.verticalAngle.ToFloat() + a.ToFloat()); return r; } \ No newline at end of file diff --git a/Spherical16.cpp b/Spherical16.cpp index b0761fb..5000841 100644 --- a/Spherical16.cpp +++ b/Spherical16.cpp @@ -13,7 +13,7 @@ Spherical16::Spherical16() { Spherical16::Spherical16(Polar polar) { this->distance = polar.distance; - this->horizontalAngle = Angle16(polar.angle); + this->horizontalAngle = Angle16(polar.angle.ToFloat()); this->verticalAngle = Angle16(0); } @@ -22,7 +22,7 @@ Spherical16::Spherical16(float distance, Angle16 verticalAngle) { if (distance < 0) { this->distance = -distance; - this->horizontalAngle = horizontalAngle - Angle16(180); + this->horizontalAngle = horizontalAngle.ToFloat() - Angle16(180).ToFloat(); this->verticalAngle = verticalAngle; } else { this->distance = distance; @@ -37,9 +37,10 @@ Spherical16::Spherical16(Vector3 v) { this->verticalAngle = 0.0f; this->horizontalAngle = 0.0f; } else { - this->verticalAngle = - (90.0f - acosf(v.Up() / this->distance) * Angle::Rad2Deg); - this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; + this->verticalAngle = (90.0f - acosf(v.Up() / this->distance) * + Passer::LinearAlgebra::Rad2Deg); + this->horizontalAngle = + atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; } } @@ -53,8 +54,8 @@ const Spherical16 Spherical16::down = Spherical16(1.0f, 0.0f, -90.0f); bool Spherical16::operator==(const Spherical16& v) const { return (this->distance == v.distance && - this->horizontalAngle == v.horizontalAngle && - this->verticalAngle == v.verticalAngle); + this->horizontalAngle.ToFloat() == v.horizontalAngle.ToFloat() && + this->verticalAngle.ToFloat() == v.verticalAngle.ToFloat()); } Spherical16 Spherical16::Normalize(const Spherical16& v) { @@ -67,16 +68,18 @@ Spherical16 Spherical16::normalized() const { } Spherical16 Spherical16::operator-() const { - Spherical16 v = Spherical16(this->distance, this->horizontalAngle + 180.0f, - this->verticalAngle + 180.0f); + Spherical16 v = + Spherical16(this->distance, this->horizontalAngle.ToFloat() + 180.0f, + this->verticalAngle.ToFloat() + 180.0f); return v; } Spherical16 Spherical16::operator-(const Spherical16& s2) const { - Spherical thisSpherical = Spherical( - this->distance, (Angle)this->horizontalAngle, (Angle)this->verticalAngle); - Spherical spherical2 = Spherical(s2.distance, (Angle)s2.horizontalAngle, - (Angle)s2.verticalAngle); + Spherical thisSpherical = + Spherical(this->distance, this->horizontalAngle.ToFloat(), + this->verticalAngle.ToFloat()); + Spherical spherical2 = Spherical(s2.distance, s2.horizontalAngle.ToFloat(), + s2.verticalAngle.ToFloat()); // let's do it the easy way... Vector3 v1 = Vector3(thisSpherical); @@ -92,10 +95,11 @@ Spherical16 Spherical16::operator-=(const Spherical16& v) { Spherical16 Spherical16::operator+(const Spherical16& s2) const { // let's do it the easy way... - Vector3 v1 = Vector3(Spherical(this->distance, (float)this->horizontalAngle, - (float)this->verticalAngle)); - Vector3 v2 = Vector3(Spherical(s2.distance, (float)s2.horizontalAngle, - (float)s2.verticalAngle)); + Vector3 v1 = + Vector3(Spherical(this->distance, this->horizontalAngle.ToFloat(), + this->verticalAngle.ToFloat())); + Vector3 v2 = Vector3(Spherical(s2.distance, s2.horizontalAngle.ToFloat(), + s2.verticalAngle.ToFloat())); Vector3 v = v1 + v2; Spherical16 r = Spherical16(v); return r; @@ -199,10 +203,10 @@ Angle Spherical16::AngleBetween(const Spherical16& v1, const Spherical16& v2) { if (denominator < epsilon) return 0.0f; - Vector3 v1_3 = Vector3(Spherical(v1.distance, (Angle)v1.horizontalAngle, - (Angle)v1.verticalAngle)); - Vector3 v2_3 = Vector3(Spherical(v2.distance, (Angle)v2.horizontalAngle, - (Angle)v2.verticalAngle)); + Vector3 v1_3 = Vector3(Spherical(v1.distance, v1.horizontalAngle.ToFloat(), + v1.verticalAngle.ToFloat())); + Vector3 v2_3 = Vector3(Spherical(v2.distance, v2.horizontalAngle.ToFloat(), + v2.verticalAngle.ToFloat())); float dot = Vector3::Dot(v1_3, v2_3); float fraction = dot / denominator; if (isnan(fraction)) @@ -216,17 +220,18 @@ Angle Spherical16::AngleBetween(const Spherical16& v1, const Spherical16& v2) { Spherical16 Spherical16::Rotate(const Spherical16& v, Angle horizontalAngle, Angle verticalAngle) { - Spherical16 r = Spherical16(v.distance, v.horizontalAngle + horizontalAngle, - v.verticalAngle + verticalAngle); + Spherical16 r = Spherical16( + v.distance, v.horizontalAngle.ToFloat() + horizontalAngle.ToFloat(), + v.verticalAngle.ToFloat() + verticalAngle.ToFloat()); return r; } Spherical16 Spherical16::RotateHorizontal(const Spherical16& v, Angle a) { - Spherical16 r = - Spherical16(v.distance, v.horizontalAngle + a, v.verticalAngle); + Spherical16 r = Spherical16( + v.distance, v.horizontalAngle.ToFloat() + a.ToFloat(), v.verticalAngle); return r; } Spherical16 Spherical16::RotateVertical(const Spherical16& v, Angle a) { - Spherical16 r = - Spherical16(v.distance, v.horizontalAngle, v.verticalAngle + a); + Spherical16 r = Spherical16(v.distance, v.horizontalAngle, + v.verticalAngle.ToFloat() + a.ToFloat()); return r; } \ No newline at end of file diff --git a/Vector2.cpp b/Vector2.cpp index a7ded06..b4b7d2d 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -30,7 +30,7 @@ Vector2::Vector2(Vector3 v) { y = v.Forward(); // z; } Vector2::Vector2(Polar p) { - float horizontalRad = p.angle * Angle::Deg2Rad; + float horizontalRad = p.angle.ToFloat() * Passer::LinearAlgebra::Deg2Rad; float cosHorizontal = cosf(horizontalRad); float sinHorizontal = sinf(horizontalRad); @@ -156,11 +156,11 @@ float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) { float angleFrom = atan2f(v1.y, v1.x); float angleTo = atan2f(v2.y, v2.x); - return -(angleTo - angleFrom) * Angle::Rad2Deg; + return -(angleTo - angleFrom) * Passer::LinearAlgebra::Rad2Deg; } Vector2 Vector2::Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a) { - float angleRad = a * Angle::Deg2Rad; + float angleRad = a.ToFloat() * Passer::LinearAlgebra::Deg2Rad; #if defined(AVR) float sinValue = sin(angleRad); float cosValue = cos(angleRad); // * Angle::Deg2Rad); diff --git a/Vector3.cpp b/Vector3.cpp index 50829d7..b8f20ff 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -31,8 +31,10 @@ Vector3::Vector3(Vector2 v) { } Vector3::Vector3(Spherical s) { - float verticalRad = (90 - s.verticalAngle) * Angle::Deg2Rad; - float horizontalRad = s.horizontalAngle * Angle::Deg2Rad; + float verticalRad = + (90.0f - s.verticalAngle.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; + float horizontalRad = + s.horizontalAngle.ToFloat() * Passer::LinearAlgebra::Deg2Rad; float cosVertical = cosf(verticalRad); float sinVertical = sinf(verticalRad); float cosHorizontal = cosf(horizontalRad); diff --git a/test/Angle_test.cc b/test/Angle_test.cc index 21b4dce..5625b2d 100644 --- a/test/Angle_test.cc +++ b/test/Angle_test.cc @@ -9,158 +9,159 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() TEST(Angle, Normalize) { - float r = 0; + Angle r = 0; r = Angle::Normalize(90.0f); - EXPECT_FLOAT_EQ(r, 90) << "Normalize 90"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize 90"; r = Angle::Normalize(-90); - EXPECT_FLOAT_EQ(r, -90) << "Normalize -90"; + EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize -90"; r = Angle::Normalize(270); - EXPECT_FLOAT_EQ(r, -90) << "Normalize 270"; + EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize 270"; r = Angle::Normalize(270 + 360); - EXPECT_FLOAT_EQ(r, -90) << "Normalize 270+360"; + EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize 270+360"; r = Angle::Normalize(-270); - EXPECT_FLOAT_EQ(r, 90) << "Normalize -270"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize -270"; r = Angle::Normalize(-270 - 360); - EXPECT_FLOAT_EQ(r, 90) << "Normalize -270-360"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize -270-360"; r = Angle::Normalize(0); - EXPECT_FLOAT_EQ(r, 0) << "Normalize 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Normalize 0"; if (std::numeric_limits::is_iec559) { r = Angle::Normalize(FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, FLOAT_INFINITY) << "Normalize INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), FLOAT_INFINITY) << "Normalize INFINITY"; r = Angle::Normalize(-FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, -FLOAT_INFINITY) << "Normalize INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), -FLOAT_INFINITY) << "Normalize INFINITY"; } } TEST(Angle, Clamp) { - float r = 0; + Angle r = 0; r = Angle::Clamp(1, 0, 2); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 2"; + EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 0 2"; r = Angle::Clamp(-1, 0, 2); - EXPECT_FLOAT_EQ(r, 0) << "Clamp -1 0 2"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp -1 0 2"; r = Angle::Clamp(3, 0, 2); - EXPECT_FLOAT_EQ(r, 2) << "Clamp 3 0 2"; + EXPECT_FLOAT_EQ(r.ToFloat(), 2) << "Clamp 3 0 2"; r = Angle::Clamp(1, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Clamp 1 0 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp 1 0 0"; r = Angle::Clamp(0, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 0 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp 0 0 0"; r = Angle::Clamp(0, 1, -1); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 0 1 -1"; + EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 0 1 -1"; if (std::numeric_limits::is_iec559) { r = Angle::Clamp(1, 0, FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 0 INFINITY"; r = Angle::Clamp(1, -FLOAT_INFINITY, 1); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 -INFINITY 1"; + EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 -INFINITY 1"; } } TEST(Angle, Difference) { - float r = 0; + Angle r = 0; r = Angle::Difference(0, 90); - EXPECT_FLOAT_EQ(r, 90) << "Difference 0 90"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference 0 90"; r = Angle::Difference(0, -90); - EXPECT_FLOAT_EQ(r, -90) << "Difference 0 -90"; + EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 0 -90"; r = Angle::Difference(0, 270); - EXPECT_FLOAT_EQ(r, -90) << "Difference 0 270"; + EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 0 270"; r = Angle::Difference(0, -270); - EXPECT_FLOAT_EQ(r, 90) << "Difference 0 -270"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference 0 -270"; r = Angle::Difference(90, 0); - EXPECT_FLOAT_EQ(r, -90) << "Difference 90 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 90 0"; r = Angle::Difference(-90, 0); - EXPECT_FLOAT_EQ(r, 90) << "Difference -90 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference -90 0"; r = Angle::Difference(0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Difference 0 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Difference 0 0"; r = Angle::Difference(90, 90); - EXPECT_FLOAT_EQ(r, 0) << "Difference 90 90"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Difference 90 90"; if (std::numeric_limits::is_iec559) { r = Angle::Difference(0, INFINITY); - EXPECT_FLOAT_EQ(r, INFINITY) << "Difference 0 INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), INFINITY) << "Difference 0 INFINITY"; r = Angle::Difference(0, -INFINITY); - EXPECT_FLOAT_EQ(r, -INFINITY) << "Difference 0 -INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), -INFINITY) << "Difference 0 -INFINITY"; r = Angle::Difference(-INFINITY, INFINITY); - EXPECT_FLOAT_EQ(r, INFINITY) << "Difference -INFINITY INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), INFINITY) << "Difference -INFINITY INFINITY"; } } TEST(Angle, MoveTowards) { - float r = 0; + Angle r = 0; r = Angle::MoveTowards(0, 90, 30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 90 30"; + EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 90 30"; r = Angle::MoveTowards(0, 90, 90); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 90"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 90"; r = Angle::MoveTowards(0, 90, 180); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 180"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 180"; r = Angle::MoveTowards(0, 90, 270); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 270"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 270"; r = Angle::MoveTowards(0, 90, -30); - EXPECT_FLOAT_EQ(r, -30) << "MoveTowards 0 90 -30"; + EXPECT_FLOAT_EQ(r.ToFloat(), -30) << "MoveTowards 0 90 -30"; r = Angle::MoveTowards(0, -90, -30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 -90 -30"; + EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 -90 -30"; r = Angle::MoveTowards(0, -90, -90); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 -90 -90"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 -90 -90"; r = Angle::MoveTowards(0, -90, -180); - EXPECT_FLOAT_EQ(r, 180) << "MoveTowards 0 -90 -180"; + EXPECT_FLOAT_EQ(r.ToFloat(), 180) << "MoveTowards 0 -90 -180"; r = Angle::MoveTowards(0, -90, -270); - EXPECT_FLOAT_EQ(r, 270) << "MoveTowards 0 -90 -270"; + EXPECT_FLOAT_EQ(r.ToFloat(), 270) << "MoveTowards 0 -90 -270"; r = Angle::MoveTowards(0, 90, 0); - EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 90 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 90 0"; r = Angle::MoveTowards(0, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 0 0"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 0 0"; r = Angle::MoveTowards(0, 0, 30); - EXPECT_FLOAT_EQ(r, 0) << "MoveTowards 0 0 30"; + EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 0 30"; if (std::numeric_limits::is_iec559) { r = Angle::MoveTowards(0, 90, FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, 90) << "MoveTowards 0 90 FLOAT_INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 FLOAT_INFINITY"; r = Angle::MoveTowards(0, FLOAT_INFINITY, 30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 FLOAT_INFINITY 30"; + EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 FLOAT_INFINITY 30"; r = Angle::MoveTowards(0, -90, -FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, FLOAT_INFINITY) << "MoveTowards 0 -90 -FLOAT_INFINITY"; + EXPECT_FLOAT_EQ(r.ToFloat(), FLOAT_INFINITY) + << "MoveTowards 0 -90 -FLOAT_INFINITY"; r = Angle::MoveTowards(0, -FLOAT_INFINITY, -30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; + EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; } } diff --git a/test/DiscreteAngle_test.cc b/test/DiscreteAngle_test.cc index bc26450..8576880 100644 --- a/test/DiscreteAngle_test.cc +++ b/test/DiscreteAngle_test.cc @@ -12,53 +12,53 @@ TEST(Angle8, Construct) { float angle = 0.0F; Angle8 a = Angle8(angle); - float f = (float)a; + float f = a.ToFloat(); EXPECT_FLOAT_EQ(f, angle); angle = -180.0F; a = Angle8(angle); - f = (float)a; + f = a.ToFloat(); EXPECT_FLOAT_EQ(f, angle); } TEST(Angle8, Negate) { float angle = 0; Angle8 a = Angle8(angle); - a = -a; - float f = (float)a; + a = -a.ToFloat(); + float f = a.ToFloat(); EXPECT_FLOAT_EQ(f, angle); angle = 90.0F; a = Angle8(angle); - a = -a; - f = (float)a; + a = -a.ToFloat(); + f = a.ToFloat(); EXPECT_FLOAT_EQ(f, -angle); } TEST(Angle8, Add) { Angle8 a = Angle8(0); Angle8 b = Angle8(0.0F); - Angle8 r = a + b; - EXPECT_FLOAT_EQ((float)r, 0); + Angle8 r = a.ToFloat() + b.ToFloat(); + EXPECT_FLOAT_EQ(r.ToFloat(), 0); } TEST(Angle16, Construct) { Angle16 a = Angle16(0.0F); - float f = (float)a; + float f = a.ToFloat(); EXPECT_FLOAT_EQ(f, 0); } TEST(Angle16, Negate) { float angle = 0; Angle16 a = Angle16(angle); - a = -a; - float f = (float)a; + a = -a.ToFloat(); + float f = a.ToFloat(); EXPECT_FLOAT_EQ(f, angle); angle = 90.0F; a = Angle16(angle); - a = -a; - f = (float)a; + a = -a.ToFloat(); + f = a.ToFloat(); EXPECT_FLOAT_EQ(f, -angle); } #endif \ No newline at end of file diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 8dfc18d..c548d0f 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Polar.h" @@ -12,19 +12,19 @@ TEST(Polar, FromVector2) { Polar p = Polar(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1"; - EXPECT_FLOAT_EQ(p.angle, 0.0F) << "s.angle 0 0 1"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "s.angle 0 0 1"; v = Vector2(1, 0); p = Polar(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0"; - EXPECT_FLOAT_EQ(p.angle, 90.0F) << "s.angle 1 0"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), 90.0F) << "s.angle 1 0"; v = Vector2(-1, 1); p = Polar(v); EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1"; - EXPECT_NEAR(p.angle, -45.0F, 1.0e-05) << "s.angle -1 1"; + EXPECT_NEAR(p.angle.ToFloat(), -45.0F, 1.0e-05) << "s.angle -1 1"; } TEST(Polar, FromSpherical) { @@ -35,37 +35,38 @@ TEST(Polar, FromSpherical) { p = Polar(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)"; - EXPECT_FLOAT_EQ(p.angle, 0.0F) << "p.angle FromSpherical(1 0 0)"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(1 0 0)"; s = Spherical(1, 45, 0); p = Polar(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)"; - EXPECT_FLOAT_EQ(p.angle, 45.0F) << "p.angle FromSpherical(1 45 0)"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), 45.0F) << "p.angle FromSpherical(1 45 0)"; s = Spherical(1, -45, 0); p = Polar(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)"; - EXPECT_FLOAT_EQ(p.angle, -45.0F) << "p.angle FromSpherical(1 -45 0)"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), -45.0F) + << "p.angle FromSpherical(1 -45 0)"; s = Spherical(0, 0, 0); p = Polar(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)"; - EXPECT_FLOAT_EQ(p.angle, 0.0F) << "p.angle FromSpherical(0 0 0)"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 0)"; s = Spherical(-1, 0, 0); p = Polar(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; - EXPECT_FLOAT_EQ(p.angle, 180.0F) << "p.angle FromSpherical(-1 0 0)"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), 180.0F) << "p.angle FromSpherical(-1 0 0)"; s = Spherical(0, 0, 90); p = Polar(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)"; - EXPECT_FLOAT_EQ(p.angle, 0.0F) << "p.angle FromSpherical(0 0 90)"; + EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 90)"; } TEST(Polar, Negation) { @@ -74,7 +75,7 @@ TEST(Polar, Negation) { r = -v; EXPECT_FLOAT_EQ(r.distance, 2); - EXPECT_FLOAT_EQ(r.angle, -135); + EXPECT_FLOAT_EQ(r.angle.ToFloat(), -135); EXPECT_TRUE(r == Polar(2, -135)) << "Negate(2 45)"; v = Polar(2, -45); @@ -88,7 +89,7 @@ TEST(Polar, Negation) { v = Polar(0, 0); r = -v; EXPECT_FLOAT_EQ(r.distance, 0.0f); - EXPECT_FLOAT_EQ(r.angle, 0.0f); + EXPECT_FLOAT_EQ(r.angle.ToFloat(), 0.0f); EXPECT_TRUE(r == Polar(0, 0)) << "Negate(0 0)"; } @@ -124,7 +125,7 @@ TEST(Polar, Addition) { v2 = Polar(1, -45); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; - EXPECT_FLOAT_EQ(r.angle, 0) << "Addition(0 0 0)"; + EXPECT_FLOAT_EQ(r.angle.ToFloat(), 0) << "Addition(0 0 0)"; } TEST(Polar, Scale_Multiply) { @@ -133,7 +134,8 @@ TEST(Polar, Scale_Multiply) { r = v1 * 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance * 2) << "ScaleMult(4 45, 2)"; - EXPECT_FLOAT_EQ(r.angle, v1.angle) << "ScaleMult(4 45, 2)"; + EXPECT_FLOAT_EQ(r.angle.ToFloat(), v1.angle.ToFloat()) + << "ScaleMult(4 45, 2)"; } TEST(Polar, Scale_Divide) { @@ -142,7 +144,7 @@ TEST(Polar, Scale_Divide) { r = v1 / 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance / 2) << "ScaleDiv(4 45, 2)"; - EXPECT_FLOAT_EQ(r.angle, v1.angle) << "ScaleDiv(4 45, 2)"; + EXPECT_FLOAT_EQ(r.angle.ToFloat(), v1.angle.ToFloat()) << "ScaleDiv(4 45, 2)"; } TEST(Polar, Distance) { @@ -164,7 +166,7 @@ TEST(Polar, Rotate) { r = Polar::Rotate(v, 45); EXPECT_FLOAT_EQ(r.distance, v.distance) << "Rotate(4 45, 45)"; - EXPECT_FLOAT_EQ(r.angle, 90.0f) << "Rotate(4 45, 45)"; + EXPECT_FLOAT_EQ(r.angle.ToFloat(), 90.0f) << "Rotate(4 45, 45)"; } #endif \ No newline at end of file diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index 318d845..4f6f5e1 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -12,22 +12,22 @@ TEST(Spherical16, FromVector3) { Spherical16 s = Spherical16(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ((float)s.horizontalAngle, 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ((float)s.verticalAngle, 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ((float)s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ((float)s.verticalAngle.ToFloat(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); s = Spherical16(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.verticalAngle, 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); s = Spherical16(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 1 0 0"; } TEST(Spherical16, FromPolar) { @@ -35,36 +35,36 @@ TEST(Spherical16, FromPolar) { Spherical16 s = Spherical16(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor Polar(1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; p = Polar(1, 45); s = Spherical16(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 45.0F) << "s.hor Polar(1 45)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 45)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; p = Polar(1, -45); s = Spherical16(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, -45.0F) << "s.hor Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; p = Polar(0, 0); s = Spherical16(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor Polar(0 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(0 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; p = Polar(-1, 0); s = Spherical16(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, -180.0F) << "s.hor Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), -180.0F) << "s.hor Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; } TEST(Spherical16, Incident1) { @@ -73,11 +73,12 @@ TEST(Spherical16, Incident1) { Spherical16 sr = Spherical16(2.49F, 98.18f, 24.4F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-02); - EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-02); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), + 1.0e-02); + EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-02); - Vector3 r = Vector3(Spherical(sr.distance, (Angle)sr.horizontalAngle, - (Angle)sr.verticalAngle)); + Vector3 r = Vector3(Spherical(sr.distance, sr.horizontalAngle.ToFloat(), + sr.verticalAngle.ToFloat())); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0"; EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0"; @@ -89,11 +90,12 @@ TEST(Spherical16, Incident2) { Spherical16 sr = Spherical16(1.4142135623F, 45.0f, 0.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); - EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), + 1.0e-05); + EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); - Vector3 r = Vector3(Spherical(sr.distance, (Angle)sr.horizontalAngle, - (Angle)sr.verticalAngle)); + Vector3 r = Vector3(Spherical(sr.distance, sr.horizontalAngle.ToFloat(), + sr.verticalAngle.ToFloat())); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); @@ -103,23 +105,24 @@ TEST(Spherical16, Incident2) { sr = Spherical16(1.4142135623F, 0.0f, 45.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); - EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), + 1.0e-05); + EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); - r = Vector3(Spherical(sr.distance, (Angle)sr.horizontalAngle, - (Angle)sr.verticalAngle)); + r = Vector3(Spherical(sr.distance, sr.horizontalAngle.ToFloat(), + sr.verticalAngle.ToFloat())); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); s = Spherical16(v); - r = Vector3( - Spherical(s.distance, (Angle)s.horizontalAngle, (Angle)s.verticalAngle)); + r = Vector3(Spherical(s.distance, s.horizontalAngle.ToFloat(), + s.verticalAngle.ToFloat())); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); - EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-02); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.verticalAngle.ToFloat(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-04); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-04); @@ -147,14 +150,14 @@ TEST(Spherical16, Addition) { v2 = Spherical16(1, -45, 0); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontalAngle, 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.verticalAngle, 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; v2 = Spherical16(1, 0, 90); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontalAngle, 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.verticalAngle, 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 0ffae7f..9d963aa 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Spherical.h" @@ -12,22 +12,22 @@ TEST(Spherical, FromVector3) { Spherical s = Spherical(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); s = Spherical(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.verticalAngle, 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); s = Spherical(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 1 0 0"; } TEST(Spherical, FromPolar) { @@ -35,36 +35,36 @@ TEST(Spherical, FromPolar) { Spherical s = Spherical(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor Polar(1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; p = Polar(1, 45); s = Spherical(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 45.0F) << "s.hor Polar(1 45)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 45)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; p = Polar(1, -45); s = Spherical(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, -45.0F) << "s.hor Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; p = Polar(0, 0); s = Spherical(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 0.0F) << "s.hor Polar(0 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(0 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; p = Polar(-1, 0); s = Spherical(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle, 180.0F) << "s.hor Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle, 0.0F) << "s.vert Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 180.0F) << "s.hor Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; } TEST(Spherical, Incident1) { @@ -73,8 +73,9 @@ TEST(Spherical, Incident1) { Spherical sr = Spherical(2.49F, 98.18f, 24.4F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-02); - EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-02); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), + 1.0e-02); + EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-02); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; @@ -88,8 +89,9 @@ TEST(Spherical, Incident2) { Spherical sr = Spherical(1.4142135623F, 45.0f, 0.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); - EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), + 1.0e-05); + EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -101,8 +103,9 @@ TEST(Spherical, Incident2) { sr = Spherical(1.4142135623F, 0.0f, 45.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle, sr.horizontalAngle, 1.0e-05); - EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), + 1.0e-05); + EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -114,8 +117,8 @@ TEST(Spherical, Incident2) { r = Vector3(s); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); - EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-02); + EXPECT_NEAR(s.horizontalAngle.ToFloat(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.verticalAngle.ToFloat(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); @@ -143,14 +146,14 @@ TEST(Spherical, Addition) { v2 = Spherical(1, -45, 0); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontalAngle, 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.verticalAngle, 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; v2 = Spherical(1, 0, 90); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontalAngle, 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.verticalAngle, 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file From 51772a18433c702244af814e0e7c24b28e904ada Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 5 Aug 2024 11:37:33 +0200 Subject: [PATCH 064/121] Added add/subtract for discrete angles --- Angle.cpp | 20 +++++++++++++ Angle.h | 4 +++ Angle16.cpp | 23 +++++++++++++++ Angle8.cpp | 23 +++++++++++++++ test/DiscreteAngle_test.cc | 57 ++++++++++++++++++++++++-------------- 5 files changed, 106 insertions(+), 21 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 3b0b3d5..c808f88 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -102,6 +102,26 @@ bool Passer::LinearAlgebra::AngleOf::operator==(AngleOf a) { return this->ToFloat() == a.ToFloat(); } +template <> +AngleOf AngleOf::operator-() const { + AngleOf angle = AngleOf(-this->value); + return angle; +} + +template <> +AngleOf AngleOf::operator-(const AngleOf& a) const { + AngleOf angle = AngleOf(); + angle.value = this->value - a.value; + return angle; +} + +template <> +AngleOf AngleOf::operator+(const AngleOf& a) const { + AngleOf angle = AngleOf(); + angle.value = this->value + a.value; + return angle; +} + template <> AngleOf AngleOf::Normalize(AngleOf angle) { float angleValue = angle.ToFloat(); diff --git a/Angle.h b/Angle.h index fc845a8..6b15e6f 100644 --- a/Angle.h +++ b/Angle.h @@ -32,6 +32,10 @@ class AngleOf { bool operator==(AngleOf a); + AngleOf operator-() const; + AngleOf operator-(const AngleOf& a) const; + AngleOf operator+(const AngleOf& a) const; + static AngleOf Normalize(AngleOf a); static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); static AngleOf Difference(AngleOf a, AngleOf b) { diff --git a/Angle16.cpp b/Angle16.cpp index e5e9cc5..c7f968a 100644 --- a/Angle16.cpp +++ b/Angle16.cpp @@ -35,6 +35,29 @@ float AngleOf::ToFloat() const { return f; } +template <> +AngleOf AngleOf::operator-() const { + AngleOf angle = AngleOf(); + angle.value = -this->value; + return angle; +} + +template <> +AngleOf AngleOf::operator-( + const AngleOf& a) const { + AngleOf angle = AngleOf(); + angle.value = this->value - a.value; + return angle; +} + +template <> +AngleOf AngleOf::operator+( + const AngleOf& a) const { + AngleOf angle = AngleOf(); + angle.value = this->value + a.value; + return angle; +} + // Not correct!!! just for syntactical compilation ATM template <> AngleOf AngleOf::CosineRuleSide( diff --git a/Angle8.cpp b/Angle8.cpp index 0ff2af0..ff14295 100644 --- a/Angle8.cpp +++ b/Angle8.cpp @@ -34,3 +34,26 @@ float AngleOf::ToFloat() const { float f = (this->value * 180) / 128.0F; return f; } + +template <> +AngleOf AngleOf::operator-() const { + AngleOf angle = AngleOf(); + angle.value = -this->value; + return angle; +} + +template <> +AngleOf AngleOf::operator-( + const AngleOf& a) const { + AngleOf angle = AngleOf(); + angle.value = this->value - a.value; + return angle; +} + +template <> +AngleOf AngleOf::operator+( + const AngleOf& a) const { + AngleOf angle = AngleOf(); + angle.value = this->value + a.value; + return angle; +} \ No newline at end of file diff --git a/test/DiscreteAngle_test.cc b/test/DiscreteAngle_test.cc index 8576880..62e505b 100644 --- a/test/DiscreteAngle_test.cc +++ b/test/DiscreteAngle_test.cc @@ -12,53 +12,68 @@ TEST(Angle8, Construct) { float angle = 0.0F; Angle8 a = Angle8(angle); - float f = a.ToFloat(); - EXPECT_FLOAT_EQ(f, angle); + EXPECT_FLOAT_EQ(a.ToFloat(), angle); angle = -180.0F; a = Angle8(angle); - f = a.ToFloat(); - EXPECT_FLOAT_EQ(f, angle); + EXPECT_FLOAT_EQ(a.ToFloat(), angle); } TEST(Angle8, Negate) { float angle = 0; Angle8 a = Angle8(angle); - a = -a.ToFloat(); - float f = a.ToFloat(); - EXPECT_FLOAT_EQ(f, angle); + a = -a; + EXPECT_FLOAT_EQ(a.ToFloat(), angle); angle = 90.0F; a = Angle8(angle); - a = -a.ToFloat(); - f = a.ToFloat(); - EXPECT_FLOAT_EQ(f, -angle); + a = -a; + EXPECT_FLOAT_EQ(a.ToFloat(), -angle); } TEST(Angle8, Add) { - Angle8 a = Angle8(0); - Angle8 b = Angle8(0.0F); - Angle8 r = a.ToFloat() + b.ToFloat(); + Angle8 a = Angle8(-45); + Angle8 b = Angle8(45.0F); + Angle8 r = a + b; EXPECT_FLOAT_EQ(r.ToFloat(), 0); } +TEST(Angle8, Subtract) { + Angle8 a = Angle8(0); + Angle8 b = Angle8(45.0F); + Angle8 r = a - b; + EXPECT_FLOAT_EQ(r.ToFloat(), -45); +} + TEST(Angle16, Construct) { Angle16 a = Angle16(0.0F); - float f = a.ToFloat(); - EXPECT_FLOAT_EQ(f, 0); + EXPECT_FLOAT_EQ(a.ToFloat(), 0); } TEST(Angle16, Negate) { float angle = 0; Angle16 a = Angle16(angle); - a = -a.ToFloat(); - float f = a.ToFloat(); - EXPECT_FLOAT_EQ(f, angle); + a = -a; + EXPECT_FLOAT_EQ(a.ToFloat(), angle); angle = 90.0F; a = Angle16(angle); - a = -a.ToFloat(); - f = a.ToFloat(); - EXPECT_FLOAT_EQ(f, -angle); + a = -a; + EXPECT_FLOAT_EQ(a.ToFloat(), -angle); } + +TEST(Angle16, Subtract) { + Angle16 a = Angle16(0); + Angle16 b = Angle16(45.0F); + Angle16 r = a - b; + EXPECT_FLOAT_EQ(r.ToFloat(), -45); +} + +TEST(Angle16, Add) { + Angle16 a = Angle16(-45); + Angle16 b = Angle16(45.0F); + Angle16 r = a + b; + EXPECT_FLOAT_EQ(r.ToFloat(), 0); +} + #endif \ No newline at end of file From 18cf653affc41afd175d1ea7ffa45203ace0bdf2 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 5 Aug 2024 11:58:53 +0200 Subject: [PATCH 065/121] Added scaling support --- Angle.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Angle.h b/Angle.h index 6b15e6f..328354b 100644 --- a/Angle.h +++ b/Angle.h @@ -36,6 +36,13 @@ class AngleOf { AngleOf operator-(const AngleOf& a) const; AngleOf operator+(const AngleOf& a) const; + friend AngleOf operator*(const AngleOf& a, float f) { + return AngleOf((float)a.ToFloat() * f); + } + friend AngleOf operator*(float f, const AngleOf& a) { + return AngleOf((float)f * a.ToFloat()); + } + static AngleOf Normalize(AngleOf a); static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); static AngleOf Difference(AngleOf a, AngleOf b) { From c72bba4f7a94d05ba2d2e5ac70684532883f782e Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 5 Aug 2024 12:16:27 +0200 Subject: [PATCH 066/121] Change Vector3::Angle return type to AngleOf --- Quaternion.cpp | 94 ++++++++++++++++++++++++-------------------- Vector3.cpp | 16 ++++---- Vector3.h | 8 ++-- test/Vector3_test.cc | 33 +++++++++------- 4 files changed, 81 insertions(+), 70 deletions(-) diff --git a/Quaternion.cpp b/Quaternion.cpp index 8f76a71..8d22db8 100644 --- a/Quaternion.cpp +++ b/Quaternion.cpp @@ -3,11 +3,12 @@ // file, You can obtain one at https ://mozilla.org/MPL/2.0/. #include "Quaternion.h" -#include "Vector3.h" #include #include +#include "Angle.h" +#include "Vector3.h" -void CopyQuat(const Quat &q1, Quat &q2) { +void CopyQuat(const Quat& q1, Quat& q2) { q2.x = q1.x; q2.y = q1.y; q2.z = q1.z; @@ -42,7 +43,9 @@ Quaternion::~Quaternion() {} const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1); -Vector3 Quaternion::xyz() const { return Vector3(x, y, z); } +Vector3 Quaternion::xyz() const { + return Vector3(x, y, z); +} float Quaternion::GetLength() const { return sqrtf(x * x + y * y + z * z + w * w); @@ -51,7 +54,7 @@ float Quaternion::GetLength() const { float Quaternion::GetLengthSquared() const { return x * x + y * y + z * z + w * w; } -float Quaternion::GetLengthSquared(const Quaternion &q) { +float Quaternion::GetLengthSquared(const Quaternion& q) { return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; } @@ -63,7 +66,7 @@ void Quaternion::Normalize() { w /= length; } -Quaternion Quaternion::Normalize(const Quaternion &q) { +Quaternion Quaternion::Normalize(const Quaternion& q) { Quaternion result; float length = q.GetLength(); result = Quaternion(q.x / length, q.y / length, q.z / length, q.w / length); @@ -74,11 +77,11 @@ float Quaternion::Dot(Quaternion a, Quaternion b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } -Vector3 Quaternion::ToAngles(const Quaternion &q1) { +Vector3 Quaternion::ToAngles(const Quaternion& q1) { float test = q1.x * q1.y + q1.z * q1.w; - if (test > 0.499f) { // singularity at north pole + if (test > 0.499f) { // singularity at north pole return Vector3(0, 2 * (float)atan2(q1.x, q1.w) * Rad2Deg, 90); - } else if (test < -0.499f) { // singularity at south pole + } else if (test < -0.499f) { // singularity at south pole return Vector3(0, -2 * (float)atan2(q1.x, q1.w) * Rad2Deg, -90); } else { float sqx = q1.x * q1.x; @@ -94,7 +97,7 @@ Vector3 Quaternion::ToAngles(const Quaternion &q1) { } } -Quaternion Quaternion::operator*(const Quaternion &r2) const { +Quaternion Quaternion::operator*(const Quaternion& r2) const { return Quaternion( this->x * r2.w + this->y * r2.z - this->z * r2.y + this->w * r2.x, -this->x * r2.z + this->y * r2.w + this->z * r2.x + this->w * r2.y, @@ -102,7 +105,7 @@ Quaternion Quaternion::operator*(const Quaternion &r2) const { -this->x * r2.x - this->y * r2.y - this->z * r2.z + this->w * r2.w); }; -Vector3 Quaternion::operator*(const Vector3 &p) const { +Vector3 Quaternion::operator*(const Vector3& p) const { float num = this->x * 2; float num2 = this->y * 2; float num3 = this->z * 2; @@ -133,7 +136,7 @@ Vector3 Quaternion::operator*(const Vector3 &p) const { return result; } -bool Quaternion::operator==(const Quaternion &q) { +bool Quaternion::operator==(const Quaternion& q) { return (this->x == q.x && this->y == q.y && this->z == q.z && this->w == q.w); } @@ -142,23 +145,23 @@ Quaternion Quaternion::Inverse(Quaternion r) { return Quaternion(-r.x / n, -r.y / n, -r.z / n, r.w / n); } -Quaternion Quaternion::LookRotation(const Vector3 &forward) { +Quaternion Quaternion::LookRotation(const Vector3& forward) { Vector3 up = Vector3(0, 1, 0); return LookRotation(forward, up); } -Quaternion Quaternion::LookRotation(const Vector3 &forward, const Vector3 &up) { +Quaternion Quaternion::LookRotation(const Vector3& forward, const Vector3& up) { Vector3 nForward = Vector3::Normalize(forward); Vector3 nRight = Vector3::Normalize(Vector3::Cross(up, nForward)); Vector3 nUp = Vector3::Cross(nForward, nRight); - float m00 = nRight.Right(); // x; - float m01 = nRight.Up(); // y; - float m02 = nRight.Forward(); // z; - float m10 = nUp.Right(); // x; - float m11 = nUp.Up(); // y; - float m12 = nUp.Forward(); // z; - float m20 = nForward.Right(); // x; - float m21 = nForward.Up(); // y; - float m22 = nForward.Forward(); // z; + float m00 = nRight.Right(); // x; + float m01 = nRight.Up(); // y; + float m02 = nRight.Forward(); // z; + float m10 = nUp.Right(); // x; + float m11 = nUp.Up(); // y; + float m12 = nUp.Forward(); // z; + float m20 = nForward.Right(); // x; + float m21 = nForward.Up(); // y; + float m22 = nForward.Forward(); // z; float num8 = (m00 + m11) + m22; Quaternion quaternion = Quaternion(); @@ -202,13 +205,13 @@ Quaternion Quaternion::FromToRotation(Vector3 fromDirection, Vector3 toDirection) { Vector3 axis = Vector3::Cross(fromDirection, toDirection); axis = Vector3::Normalize(axis); - float angle = Vector3::SignedAngle(fromDirection, toDirection, axis); - Quaternion rotation = Quaternion::AngleAxis(angle, axis); + AngleOf angle = Vector3::SignedAngle(fromDirection, toDirection, axis); + Quaternion rotation = Quaternion::AngleAxis(angle.ToFloat(), axis); return rotation; } -Quaternion Quaternion::RotateTowards(const Quaternion &from, - const Quaternion &to, +Quaternion Quaternion::RotateTowards(const Quaternion& from, + const Quaternion& to, float maxDegreesDelta) { float num = Quaternion::Angle(from, to); if (num == 0) { @@ -218,7 +221,7 @@ Quaternion Quaternion::RotateTowards(const Quaternion &from, return SlerpUnclamped(from, to, t); } -Quaternion Quaternion::AngleAxis(float angle, const Vector3 &axis) { +Quaternion Quaternion::AngleAxis(float angle, const Vector3& axis) { if (Vector3::SqrMagnitude(axis) == 0.0f) return Quaternion(); @@ -227,9 +230,9 @@ Quaternion Quaternion::AngleAxis(float angle, const Vector3 &axis) { radians *= 0.5f; Vector3 axis2 = axis * (float)sin(radians); - result.x = axis2.Right(); // x; - result.y = axis2.Up(); // y; - result.z = axis2.Forward(); // z; + result.x = axis2.Right(); // x; + result.y = axis2.Up(); // y; + result.z = axis2.Forward(); // z; result.w = (float)cos(radians); return Quaternion::Normalize(result); @@ -240,15 +243,16 @@ float Quaternion::Angle(Quaternion a, Quaternion b) { return (float)acos(fmin(fabs(f), 1)) * 2 * Rad2Deg; } -void Quaternion::ToAngleAxis(float *angle, Vector3 *axis) { +void Quaternion::ToAngleAxis(float* angle, Vector3* axis) { Quaternion::ToAxisAngleRad(*this, axis, angle); *angle *= Rad2Deg; } -void Quaternion::ToAxisAngleRad(const Quaternion &q, Vector3 *const axis, - float *angle) { +void Quaternion::ToAxisAngleRad(const Quaternion& q, + Vector3* const axis, + float* angle) { Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q; - *angle = 2.0f * acosf(q1.w); // angle + *angle = 2.0f * acosf(q1.w); // angle float den = sqrtf(1.0F - q1.w * q1.w); if (den > 0.0001f) { *axis = Vector3::Normalize(q1.xyz() / den); @@ -258,7 +262,8 @@ void Quaternion::ToAxisAngleRad(const Quaternion &q, Vector3 *const axis, *axis = Vector3(1, 0, 0); } } -Quaternion Quaternion::SlerpUnclamped(const Quaternion &a, const Quaternion &b, +Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, + const Quaternion& b, float t) { // if either input is zero, return the other. if (Quaternion::GetLengthSquared(a) == 0.0f) { @@ -309,7 +314,8 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion &a, const Quaternion &b, return Quaternion(); } -Quaternion Quaternion::Slerp(const Quaternion &a, const Quaternion &b, +Quaternion Quaternion::Slerp(const Quaternion& a, + const Quaternion& b, float t) { if (t > 1) t = 1; @@ -357,9 +363,9 @@ Quaternion Quaternion::EulerXYZ(Vector3 euler) { return Quaternion::FromEulerRadXYZ(euler * Deg2Rad); } Quaternion Quaternion::FromEulerRadXYZ(Vector3 euler) { - float yaw = euler.Right(); // x; - float pitch = euler.Up(); // y; - float roll = euler.Forward(); // z; + float yaw = euler.Right(); // x; + float pitch = euler.Up(); // y; + float roll = euler.Forward(); // z; float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)sin((float)rollOver2); float cosRollOver2 = (float)cos((float)rollOver2); @@ -395,16 +401,18 @@ float Quaternion::GetAngleAround(Vector3 axis, Quaternion rotation) { } Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) { - Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis + Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis Vector3 p = Vector3::Project( - ra, axis); // return projection ra on to axis (parallel component) + ra, axis); // return projection ra on to axis (parallel component) Quaternion twist = Quaternion(p.Right(), p.Up(), p.Forward(), rotation.w); twist = Quaternion::Normalize(twist); return twist; } -void Quaternion::GetSwingTwist(Vector3 axis, Quaternion rotation, - Quaternion *swing, Quaternion *twist) { +void Quaternion::GetSwingTwist(Vector3 axis, + Quaternion rotation, + Quaternion* swing, + Quaternion* twist) { *twist = GetRotationAround(axis, rotation); *swing = rotation * Quaternion::Inverse(*twist); } diff --git a/Vector3.cpp b/Vector3.cpp index b8f20ff..36c2b3b 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -188,7 +188,7 @@ float clamp(float x, float lower, float upper) { return upperClamp; } -float Vector3::Angle(const Vector3& v1, const Vector3& v2) { +AngleOf Vector3::Angle(const Vector3& v1, const Vector3& v2) { float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude()); if (denominator < epsilon) return 0; @@ -200,23 +200,23 @@ float Vector3::Angle(const Vector3& v1, const Vector3& v2) { float cdot = clamp(fraction, -1.0, 1.0); float r = ((float)acos(cdot)) * Rad2Deg; - return r; + return AngleOf(r); } -float Vector3::SignedAngle(const Vector3& v1, - const Vector3& v2, - const Vector3& axis) { +AngleOf Vector3::SignedAngle(const Vector3& v1, + const Vector3& v2, + const Vector3& axis) { // angle in [0,180] - float angle = Vector3::Angle(v1, v2); + AngleOf angle = Vector3::Angle(v1, v2); Vector3 cross = Vector3::Cross(v1, v2); float b = Vector3::Dot(axis, cross); float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F); // angle in [-179,180] - float signed_angle = angle * signd; + AngleOf signed_angle = angle * signd; - return signed_angle; + return AngleOf(signed_angle); } Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) { diff --git a/Vector3.h b/Vector3.h index f17eae8..4f8aa1d 100644 --- a/Vector3.h +++ b/Vector3.h @@ -204,15 +204,15 @@ struct Vector3 : Vec3 { /// @remark This reterns an unsigned angle which is the shortest distance /// between the two vectors. Use Vector3::SignedAngle if a signed angle is /// needed. - static float Angle(const Vector3& v1, const Vector3& v2); + static AngleOf Angle(const Vector3& v1, const Vector3& v2); /// @brief The signed angle between two vectors /// @param v1 The starting vector /// @param v2 The ending vector /// @param axis The axis to rotate around /// @return The signed angle between the two vectors - static float SignedAngle(const Vector3& v1, - const Vector3& v2, - const Vector3& axis); + static AngleOf SignedAngle(const Vector3& v1, + const Vector3& v2, + const Vector3& axis); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index 4e5003c..c7ba095 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Vector3.h" @@ -488,29 +488,29 @@ TEST(Vector3, ProjectOnPlane) { TEST(Vector3, Angle) { Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); - float f = 0; + AngleOf f = 0; bool r = false; f = Vector3::Angle(v1, v2); - EXPECT_FLOAT_EQ(f, 12.9331388F) << "Angle(4 5 6, 1 2 3)"; + EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F) << "Angle(4 5 6, 1 2 3)"; v2 = Vector3(-1, -2, -3); f = Vector3::Angle(v1, v2); - EXPECT_FLOAT_EQ(f, 167.066864F) << "Angle(4 5 6, -1 -2 -3)"; + EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F) << "Angle(4 5 6, -1 -2 -3)"; v2 = Vector3(0, 0, 0); f = Vector3::Angle(v1, v2); - EXPECT_FLOAT_EQ(f, 0) << "Angle(4 5 6, 0 0 0)"; + EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "Angle(4 5 6, 0 0 0)"; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); f = Vector3::Angle(v1, v2); - r = isnan(f); + r = isnan(f.ToFloat()); EXPECT_TRUE(r) << "Angle(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); f = Vector3::Angle(v1, v2); - r = isnan(f); + r = isnan(f.ToFloat()); EXPECT_TRUE(r) << "Angle(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -519,39 +519,42 @@ TEST(Vector3, SignedAngle) { Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v3 = Vector3(7, 8, -9); - float f = 0; + AngleOf f = 0; bool r = false; f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f, -12.9331388F) << "SignedAngle(4 5 6, 1 2 3, 7 8 -9)"; + EXPECT_FLOAT_EQ(f.ToFloat(), -12.9331388F) + << "SignedAngle(4 5 6, 1 2 3, 7 8 -9)"; v2 = Vector3(-1, -2, -3); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f, 167.066864F) << "SignedAngle(4 5 6, -1 -2 -3, 7 8 -9)"; + EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F) + << "SignedAngle(4 5 6, -1 -2 -3, 7 8 -9)"; v2 = Vector3(0, 0, 0); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f, 0) << "SignedAngle(4 5 6, 0 0 0, 7 8 -9 )"; + EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 0 0 0, 7 8 -9 )"; v2 = Vector3(1, 2, 3); v3 = Vector3(-7, -8, 9); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f, 12.9331388F) << "SignedAngle(4 5 6, 1 2 3, -7 -8 9)"; + EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F) + << "SignedAngle(4 5 6, 1 2 3, -7 -8 9)"; v3 = Vector3(0, 0, 0); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f, 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)"; + EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)"; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); f = Vector3::SignedAngle(v1, v2, v3); - r = isnan(f); + r = isnan(f.ToFloat()); EXPECT_TRUE(r) << "SignedAngle(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); f = Vector3::SignedAngle(v1, v2, v3); - r = isnan(f); + r = isnan(f.ToFloat()); EXPECT_TRUE(r) << "SignedAngle(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } From 38ebb34491d66685436240031754c1cb82856fb0 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 6 Aug 2024 09:14:33 +0200 Subject: [PATCH 067/121] Added Direction to replace Axis --- AngleAxis.cpp | 6 ++++-- AngleAxis.h | 16 +++++++++------- Direction.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ Direction.h | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 Direction.cpp create mode 100644 Direction.h diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 9cc1f1e..8dad1b1 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -4,12 +4,14 @@ #include "AngleAxis.h" -AngleAxis::AngleAxis() { +template +AngleAxis::AngleAxis() { angle = Angle(); axis = Axis(); } -AngleAxis::AngleAxis(Angle angle, Axis axis) { +template +AngleAxis::AngleAxis(AngleOf angle, Direction axis) { this->angle = angle; this->axis = axis; } \ No newline at end of file diff --git a/AngleAxis.h b/AngleAxis.h index 7dd47ab..c9e1fd5 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -6,22 +6,24 @@ #define ANGLEAXIS_H #include "Angle.h" -#include "Axis.h" +// #include "Axis.h" +#include "Direction.h" namespace Passer { namespace LinearAlgebra { +template class AngleAxis { -public: - Angle angle; - Axis axis; + public: + AngleOf angle; + Direction axis; AngleAxis(); - AngleAxis(Angle angle, Axis axis); + AngleAxis(AngleOf angle, Direction axis); }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #endif \ No newline at end of file diff --git a/Direction.cpp b/Direction.cpp new file mode 100644 index 0000000..925bee3 --- /dev/null +++ b/Direction.cpp @@ -0,0 +1,50 @@ +// 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 "Direction.h" + +#include "Quaternion.h" +#include "Vector3.h" + +#include + +template +Direction::Direction() { + this->horizontalAngle = AngleOf(0.0f); + this->verticalAngle = AngleOf(0.0f); +} + +template +Direction::Direction(AngleOf horizontal, AngleOf vertical) { + this->horizontalAngle = horizontal; + this->verticalAngle = vertical; +}; + +template +Direction::Direction(Vector3 v) { + this->horizontalAngle = + atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; + this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; +} + +template +const Direction Direction::forward = Direction(0.0f, 0.0f); +template +const Direction Direction::back = Direction(180.0f, 0.0f); +template +const Direction Direction::up = Direction(0.0f, 90.0f); +template +const Direction Direction::down = Direction(0.0f, -90.0f); +template +const Direction Direction::left = Direction(-90.0f, 0.0f); +template +const Direction Direction::right = Direction(90.0f, 0.0f); + +template +Vector3 Direction::ToVector3() { + Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), + this->horizontalAngle.ToFloat(), 0) * + Vector3::forward; + return v; +} \ No newline at end of file diff --git a/Direction.h b/Direction.h new file mode 100644 index 0000000..6978b0a --- /dev/null +++ b/Direction.h @@ -0,0 +1,39 @@ +// 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/. + +#ifndef DIRECTION_H +#define DIRECTION_H + +#include "Angle.h" + +namespace Passer { +namespace LinearAlgebra { + +struct Vector3; + +template +class Direction { + public: + AngleOf horizontalAngle; + AngleOf verticalAngle; + + Direction(); + Direction(AngleOf horizontal, AngleOf vertical); + Direction(Vector3 v); + + const static Direction forward; + const static Direction back; + const static Direction up; + const static Direction down; + const static Direction left; + const static Direction right; + + Vector3 ToVector3(); +}; + +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#endif \ No newline at end of file From 1ce7234d711dafc92253bd526e413e22b8ecd7c3 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 6 Aug 2024 09:28:54 +0200 Subject: [PATCH 068/121] Bug fixes --- AngleAxis.cpp | 4 ++-- AngleAxis.h | 1 - Direction.cpp | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 8dad1b1..529f5d1 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -6,8 +6,8 @@ template AngleAxis::AngleAxis() { - angle = Angle(); - axis = Axis(); + this->angle = Angle(); + this->axis = Direction(); } template diff --git a/AngleAxis.h b/AngleAxis.h index c9e1fd5..a79bd1e 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -6,7 +6,6 @@ #define ANGLEAXIS_H #include "Angle.h" -// #include "Axis.h" #include "Direction.h" namespace Passer { diff --git a/Direction.cpp b/Direction.cpp index 925bee3..af31a58 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -11,8 +11,8 @@ template Direction::Direction() { - this->horizontalAngle = AngleOf(0.0f); - this->verticalAngle = AngleOf(0.0f); + this->horizontalAngle = AngleOf(0.0f); + this->verticalAngle = AngleOf(0.0f); } template From ea6894e05b2040cfedcbf063e48dd0d11e96b2d9 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 6 Aug 2024 09:47:48 +0200 Subject: [PATCH 069/121] Fix generic template functions --- AngleAxis.cpp | 39 +++++++++++++++++++++++++++++---------- AngleAxis.h | 37 +++++++++++++++++++++++++++++++++++++ Direction.cpp | 46 +++++++++++++++++++++++----------------------- Direction.h | 31 +++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 33 deletions(-) diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 529f5d1..98b6d7a 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -4,14 +4,33 @@ #include "AngleAxis.h" -template -AngleAxis::AngleAxis() { - this->angle = Angle(); - this->axis = Direction(); -} +// template +// AngleAxis::AngleAxis() { +// this->angle = Angle(); +// this->axis = Direction(); +// } -template -AngleAxis::AngleAxis(AngleOf angle, Direction axis) { - this->angle = angle; - this->axis = axis; -} \ No newline at end of file +// template +// AngleAxis::AngleAxis(AngleOf angle, Direction axis) { +// this->angle = angle; +// this->axis = axis; +// } + +// template +// AngleAxis::AngleAxis(float angle, Vector3 axis) { +// this->angle = AngleOf(angle); +// this->axis = Direction(axis); +// } + +// template +// Quaternion AngleAxis::ToQuaternion() { +// Vector3 axisVector = this->axis.ToVector3(); +// float angleFloat = this->angle.ToFloat(); +// Quaternion q = Quaternion::AngleAxis(angleFloat, axisVector); +// return q; +// } + +// template +// Direction AngleAxis::GetSwing() { +// return this->axis; +// } \ No newline at end of file diff --git a/AngleAxis.h b/AngleAxis.h index a79bd1e..2df36dd 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -7,6 +7,7 @@ #include "Angle.h" #include "Direction.h" +#include "Quaternion.h" namespace Passer { namespace LinearAlgebra { @@ -19,10 +20,46 @@ class AngleAxis { AngleAxis(); AngleAxis(AngleOf angle, Direction axis); + AngleAxis(float angle, Vector3 axis); + + Quaternion ToQuaternion(); + + Direction GetSwing(); }; +template +Quaternion AngleAxis::ToQuaternion() { + Vector3 axisVector = this->axis.ToVector3(); + float angleFloat = this->angle.ToFloat(); + Quaternion q = Quaternion::AngleAxis(angleFloat, axisVector); + return q; +} + } // namespace LinearAlgebra } // namespace Passer using namespace Passer::LinearAlgebra; +template +AngleAxis::AngleAxis() { + this->angle = Angle(); + this->axis = Direction(); +} + +template +AngleAxis::AngleAxis(AngleOf angle, Direction axis) { + this->angle = angle; + this->axis = axis; +} + +template +AngleAxis::AngleAxis(float angle, Vector3 axis) { + this->angle = AngleOf(angle); + this->axis = Direction(axis); +} + +template +Direction AngleAxis::GetSwing() { + return this->axis; +} + #endif \ No newline at end of file diff --git a/Direction.cpp b/Direction.cpp index af31a58..4cd40be 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -9,24 +9,24 @@ #include -template -Direction::Direction() { - this->horizontalAngle = AngleOf(0.0f); - this->verticalAngle = AngleOf(0.0f); -} +// template +// Direction::Direction() { +// this->horizontalAngle = AngleOf(0.0f); +// this->verticalAngle = AngleOf(0.0f); +// } -template -Direction::Direction(AngleOf horizontal, AngleOf vertical) { - this->horizontalAngle = horizontal; - this->verticalAngle = vertical; -}; +// template +// Direction::Direction(AngleOf horizontal, AngleOf vertical) { +// this->horizontalAngle = horizontal; +// this->verticalAngle = vertical; +// }; -template -Direction::Direction(Vector3 v) { - this->horizontalAngle = - atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; - this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; -} +// template +// Direction::Direction(Vector3 v) { +// this->horizontalAngle = +// atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; +// this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; +// } template const Direction Direction::forward = Direction(0.0f, 0.0f); @@ -41,10 +41,10 @@ const Direction Direction::left = Direction(-90.0f, 0.0f); template const Direction Direction::right = Direction(90.0f, 0.0f); -template -Vector3 Direction::ToVector3() { - Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), - this->horizontalAngle.ToFloat(), 0) * - Vector3::forward; - return v; -} \ No newline at end of file +// template +// Vector3 Direction::ToVector3() { +// Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), +// this->horizontalAngle.ToFloat(), 0) * +// Vector3::forward; +// return v; +// } \ No newline at end of file diff --git a/Direction.h b/Direction.h index 6978b0a..755855a 100644 --- a/Direction.h +++ b/Direction.h @@ -36,4 +36,35 @@ class Direction { } // namespace Passer using namespace Passer::LinearAlgebra; +#include +#include "Quaternion.h" +#include "Vector3.h" + +template +Direction::Direction() { + this->horizontalAngle = AngleOf(0.0f); + this->verticalAngle = AngleOf(0.0f); +} + +template +Direction::Direction(AngleOf horizontal, AngleOf vertical) { + this->horizontalAngle = horizontal; + this->verticalAngle = vertical; +}; + +template +Direction::Direction(Vector3 v) { + this->horizontalAngle = + atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; + this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; +} + +template +Vector3 Direction::ToVector3() { + Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), + this->horizontalAngle.ToFloat(), 0) * + Vector3::forward; + return v; +} + #endif \ No newline at end of file From cf86ba82ac3b7936b7c128a221eb3def70ab0e16 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 6 Aug 2024 10:02:01 +0200 Subject: [PATCH 070/121] Cleanup template classes --- AngleAxis.cpp | 55 +++++++++++++++++++++++++++------------------------ AngleAxis.h | 31 ----------------------------- Direction.cpp | 50 +++++++++++++++++++++++++--------------------- Direction.h | 31 ----------------------------- 4 files changed, 56 insertions(+), 111 deletions(-) diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 98b6d7a..49379ef 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -4,33 +4,36 @@ #include "AngleAxis.h" -// template -// AngleAxis::AngleAxis() { -// this->angle = Angle(); -// this->axis = Direction(); -// } +template +AngleAxis::AngleAxis() { + this->angle = AngleOf(); + this->axis = Direction(); +} -// template -// AngleAxis::AngleAxis(AngleOf angle, Direction axis) { -// this->angle = angle; -// this->axis = axis; -// } +template +AngleAxis::AngleAxis(AngleOf angle, Direction axis) { + this->angle = angle; + this->axis = axis; +} -// template -// AngleAxis::AngleAxis(float angle, Vector3 axis) { -// this->angle = AngleOf(angle); -// this->axis = Direction(axis); -// } +template +AngleAxis::AngleAxis(float angle, Vector3 axis) { + this->angle = AngleOf(angle); + this->axis = Direction(axis); +} -// template -// Quaternion AngleAxis::ToQuaternion() { -// Vector3 axisVector = this->axis.ToVector3(); -// float angleFloat = this->angle.ToFloat(); -// Quaternion q = Quaternion::AngleAxis(angleFloat, axisVector); -// return q; -// } +template +Quaternion AngleAxis::ToQuaternion() { + Vector3 axisVector = this->axis.ToVector3(); + float angleFloat = this->angle.ToFloat(); + Quaternion q = Quaternion::AngleAxis(angleFloat, axisVector); + return q; +} -// template -// Direction AngleAxis::GetSwing() { -// return this->axis; -// } \ No newline at end of file +template +Direction AngleAxis::GetSwing() { + return this->axis; +} + +template class AngleAxis; +template class AngleAxis; diff --git a/AngleAxis.h b/AngleAxis.h index 2df36dd..14e2f3d 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -27,39 +27,8 @@ class AngleAxis { Direction GetSwing(); }; -template -Quaternion AngleAxis::ToQuaternion() { - Vector3 axisVector = this->axis.ToVector3(); - float angleFloat = this->angle.ToFloat(); - Quaternion q = Quaternion::AngleAxis(angleFloat, axisVector); - return q; -} - } // namespace LinearAlgebra } // namespace Passer using namespace Passer::LinearAlgebra; -template -AngleAxis::AngleAxis() { - this->angle = Angle(); - this->axis = Direction(); -} - -template -AngleAxis::AngleAxis(AngleOf angle, Direction axis) { - this->angle = angle; - this->axis = axis; -} - -template -AngleAxis::AngleAxis(float angle, Vector3 axis) { - this->angle = AngleOf(angle); - this->axis = Direction(axis); -} - -template -Direction AngleAxis::GetSwing() { - return this->axis; -} - #endif \ No newline at end of file diff --git a/Direction.cpp b/Direction.cpp index 4cd40be..f17f271 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -9,24 +9,24 @@ #include -// template -// Direction::Direction() { -// this->horizontalAngle = AngleOf(0.0f); -// this->verticalAngle = AngleOf(0.0f); -// } +template +Direction::Direction() { + this->horizontalAngle = AngleOf(0.0f); + this->verticalAngle = AngleOf(0.0f); +} -// template -// Direction::Direction(AngleOf horizontal, AngleOf vertical) { -// this->horizontalAngle = horizontal; -// this->verticalAngle = vertical; -// }; +template +Direction::Direction(AngleOf horizontal, AngleOf vertical) { + this->horizontalAngle = horizontal; + this->verticalAngle = vertical; +}; -// template -// Direction::Direction(Vector3 v) { -// this->horizontalAngle = -// atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; -// this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; -// } +template +Direction::Direction(Vector3 v) { + this->horizontalAngle = + atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; + this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; +} template const Direction Direction::forward = Direction(0.0f, 0.0f); @@ -41,10 +41,14 @@ const Direction Direction::left = Direction(-90.0f, 0.0f); template const Direction Direction::right = Direction(90.0f, 0.0f); -// template -// Vector3 Direction::ToVector3() { -// Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), -// this->horizontalAngle.ToFloat(), 0) * -// Vector3::forward; -// return v; -// } \ No newline at end of file +template +Vector3 Direction::ToVector3() { + Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), + this->horizontalAngle.ToFloat(), 0) * + Vector3::forward; + return v; +} + +template class Direction; +template class Direction; +template class Direction; \ No newline at end of file diff --git a/Direction.h b/Direction.h index 755855a..6978b0a 100644 --- a/Direction.h +++ b/Direction.h @@ -36,35 +36,4 @@ class Direction { } // namespace Passer using namespace Passer::LinearAlgebra; -#include -#include "Quaternion.h" -#include "Vector3.h" - -template -Direction::Direction() { - this->horizontalAngle = AngleOf(0.0f); - this->verticalAngle = AngleOf(0.0f); -} - -template -Direction::Direction(AngleOf horizontal, AngleOf vertical) { - this->horizontalAngle = horizontal; - this->verticalAngle = vertical; -}; - -template -Direction::Direction(Vector3 v) { - this->horizontalAngle = - atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; - this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; -} - -template -Vector3 Direction::ToVector3() { - Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), - this->horizontalAngle.ToFloat(), 0) * - Vector3::forward; - return v; -} - #endif \ No newline at end of file From 353cb1bc7f3c12f703c0f963d89d08d567fc446a Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 6 Aug 2024 12:08:19 +0200 Subject: [PATCH 071/121] Add conversion from Quaternion --- AngleAxis.cpp | 9 +++++++++ AngleAxis.h | 1 + 2 files changed, 10 insertions(+) diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 49379ef..2ed8321 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -22,6 +22,15 @@ AngleAxis::AngleAxis(float angle, Vector3 axis) { this->axis = Direction(axis); } +template +AngleAxis::AngleAxis(Quaternion q) { + float angle; + Vector3 axis; + q.ToAngleAxis(&angle, &axis); + this->angle = AngleOf(angle); + this->axis = Direction(axis); +} + template Quaternion AngleAxis::ToQuaternion() { Vector3 axisVector = this->axis.ToVector3(); diff --git a/AngleAxis.h b/AngleAxis.h index 14e2f3d..fbd0ec2 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -20,6 +20,7 @@ class AngleAxis { AngleAxis(); AngleAxis(AngleOf angle, Direction axis); + AngleAxis(Quaternion q); AngleAxis(float angle, Vector3 axis); Quaternion ToQuaternion(); From 9c3503f3cb678622fcdc7935b791a28c6c48d052 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 22 Aug 2024 12:28:02 +0200 Subject: [PATCH 072/121] Added SphericalOf --- Angle.cpp | 12 +++- Angle.h | 1 + Spherical.cpp | 183 ++++++++++++++++++++++++++++++++++++++++++++++++ Spherical.h | 55 +++++++++++++++ Spherical16.cpp | 26 ++++++- Spherical16.h | 6 +- 6 files changed, 277 insertions(+), 6 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index c808f88..4948086 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -98,7 +98,7 @@ float AngleOf::ToFloat() const { // AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; template <> -bool Passer::LinearAlgebra::AngleOf::operator==(AngleOf a) { +bool AngleOf::operator==(AngleOf a) { return this->ToFloat() == a.ToFloat(); } @@ -122,6 +122,12 @@ AngleOf AngleOf::operator+(const AngleOf& a) const { return angle; } +template +AngleOf AngleOf::operator+=(const AngleOf& a) { + this->value += a.value; + return *this; +} + template <> AngleOf AngleOf::Normalize(AngleOf angle) { float angleValue = angle.ToFloat(); @@ -200,4 +206,6 @@ AngleOf AngleOf::SineRuleAngle(float a, float deg2rad = Passer::LinearAlgebra::Deg2Rad; float alpha = asinf(a * sinf(beta.ToFloat() * deg2rad) / b); return alpha; -} \ No newline at end of file +} +template class AngleOf; +template class AngleOf; diff --git a/Angle.h b/Angle.h index 328354b..37c2758 100644 --- a/Angle.h +++ b/Angle.h @@ -35,6 +35,7 @@ class AngleOf { AngleOf operator-() const; AngleOf operator-(const AngleOf& a) const; AngleOf operator+(const AngleOf& a) const; + AngleOf operator+=(const AngleOf& a); friend AngleOf operator*(const AngleOf& a, float f) { return AngleOf((float)a.ToFloat() * f); diff --git a/Spherical.cpp b/Spherical.cpp index f1a80d1..dca766b 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -5,6 +5,189 @@ #include +template +SphericalOf::SphericalOf() { + this->distance = 0.0f; + this->horizontal = AngleOf(0); + this->vertical = AngleOf(0); +} + +// template <> +// SphericalOf::SphericalOf() { +// this->distance = 0.0f; +// this->horizontal = AngleOf(0); +// this->vertical = AngleOf(0); +// } + +template +SphericalOf::SphericalOf(float distance, + AngleOf horizontal, + AngleOf vertical) { + this->distance = distance; + this->horizontal = horizontal; + this->vertical = vertical; +} + +// template <> +// SphericalOf::SphericalOf(float distance, +// AngleOf horizontal, +// AngleOf vertical) { +// this->distance = distance; +// this->horizontal = horizontal; +// this->vertical = vertical; +// } + +// template <> +// SphericalOf::SphericalOf(float distance, +// AngleOf horizontal, +// AngleOf vertical) { +// this->distance = distance; +// this->horizontal = horizontal; +// this->vertical = vertical; +// } + +template +SphericalOf SphericalOf::FromVector3(Vector3 v) { + float distance = v.magnitude(); + if (distance == 0.0f) { + return SphericalOf(distance, 0, 0); + } else { + float verticalAngle = + (90.0f - acosf(v.Up() / distance) * Passer::LinearAlgebra::Rad2Deg); + float horizontalAngle = + atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; + return SphericalOf(distance, horizontalAngle, verticalAngle); + } +} + +template +Vector3 SphericalOf::ToVector3() const { + float verticalRad = + (90.0f - this->vertical.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; + float horizontalRad = + this->horizontal.ToFloat() * Passer::LinearAlgebra::Deg2Rad; + float cosVertical = cosf(verticalRad); + float sinVertical = sinf(verticalRad); + float cosHorizontal = cosf(horizontalRad); + float sinHorizontal = sinf(horizontalRad); + + float x = this->distance * sinVertical * sinHorizontal; + float y = this->distance * cosVertical; + float z = this->distance * sinVertical * cosHorizontal; + + Vector3 v = Vector3(x, y, z); + return Vector3(); +} + +template +const SphericalOf SphericalOf::zero = + SphericalOf(0.0f, AngleOf(0), AngleOf(0)); +template +const SphericalOf SphericalOf::forward = SphericalOf(1.0f, 0.0f, 0.0f); +template +const SphericalOf SphericalOf::back = SphericalOf(1.0f, 180.0f, 0.0f); +template +const SphericalOf SphericalOf::right = SphericalOf(1.0f, 90.0f, 0.0f); +template +const SphericalOf SphericalOf::left = SphericalOf(1.0f, -90.0f, 0.0f); +template +const SphericalOf SphericalOf::up = SphericalOf(1.0f, 0.0f, 90.0f); +template +const SphericalOf SphericalOf::down = SphericalOf(1.0f, 0.0f, -90.0f); + +template <> +const SphericalOf SphericalOf::zero = + SphericalOf(0.0f, AngleOf(0), AngleOf(0)); + +template +SphericalOf SphericalOf::operator-() const { + SphericalOf v = + SphericalOf(this->distance, this->horizontal.ToFloat() + 180.0f, + this->vertical.ToFloat() + 180.0f); + return v; +} + +template +SphericalOf SphericalOf::operator-(const SphericalOf& s2) const { + // let's do it the easy way... + Vector3 v1 = this->ToVector3(); + Vector3 v2 = s2.ToVector3(); + Vector3 v = v1 - v2; + SphericalOf r = SphericalOf::FromVector3(v); + return r; +} +template +SphericalOf SphericalOf::operator-=(const SphericalOf& v) { + *this = *this - v; + return *this; +} + +template +SphericalOf SphericalOf::operator+(const SphericalOf& s2) const { + // let's do it the easy way... + Vector3 v1 = this->ToVector3(); + Vector3 v2 = s2.ToVector3(); + Vector3 v = v1 + v2; + SphericalOf r = SphericalOf::FromVector3(v); + return r; + /* + // This is the hard way... + if (v2.distance <= 0) + return Spherical(this->distance, this->horizontalAngle, + this->verticalAngle); + if (this->distance <= 0) + return v2; + + float deltaHorizontalAngle = + (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); + float horizontalRotation = deltaHorizontalAngle < 0 + ? 180 + deltaHorizontalAngle + : 180 - deltaHorizontalAngle; + float deltaVerticalAngle = + Angle::Normalize(v2.verticalAngle - this->verticalAngle); + float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle + : 180 - deltaVerticalAngle; + + if (horizontalRotation == 180 && verticalRotation == 180) + // angle is too small, take this angle and add the distances + return Spherical(this->distance + v2.distance, this->horizontalAngle, + this->verticalAngle); + + Angle rotation = AngleBetween(*this, v2); + float newDistance = + Angle::CosineRuleSide(v2.distance, this->distance, rotation); + float angle = + Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); + + // Now we have to project the angle to the horizontal and vertical planes... + // The axis for the angle is the cross product of the two spherical vectors + // (which function we do not have either...) + float horizontalAngle = 0; + float verticalAngle = 0; + + float newHorizontalAngle = + deltaHorizontalAngle < 0 + ? Angle::Normalize(this->horizontalAngle - horizontalAngle) + : Angle::Normalize(this->horizontalAngle + horizontalAngle); + float newVerticalAngle = + deltaVerticalAngle < 0 + ? Angle::Normalize(this->verticalAngle - verticalAngle) + : Angle::Normalize(this->verticalAngle + verticalAngle); + + Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); + */ +} +template +SphericalOf SphericalOf::operator+=(const SphericalOf& v) { + *this = *this + v; + return *this; +} + +template class SphericalOf; +template class SphericalOf; + +//--------------------------------------- + Spherical::Spherical() { this->distance = 0.0f; this->horizontalAngle = 0.0f; diff --git a/Spherical.h b/Spherical.h index 112f5e0..37799df 100644 --- a/Spherical.h +++ b/Spherical.h @@ -13,6 +13,61 @@ namespace LinearAlgebra { struct Vector3; +template +class SphericalOf { + public: + /// @brief The distance in meters + /// @remark The distance should never be negative + float distance; + /// @brief The angle in the horizontal plane in degrees, clockwise rotation + /// @details The angle is automatically normalized to -180 .. 180 + AngleOf horizontal; + /// @brief The angle in the vertical plane in degrees. Positive is upward. + /// @details The angle is automatically normalized to -180 .. 180 + AngleOf vertical; + + SphericalOf(); + SphericalOf(float distance, AngleOf horizontal, AngleOf vertical); + + static SphericalOf FromVector3(Vector3 v); + Vector3 ToVector3() const; + + /// @brief A spherical vector with zero degree angles and distance + const static SphericalOf zero; + /// @brief A normalized forward-oriented vector + const static SphericalOf forward; + /// @brief A normalized back-oriented vector + const static SphericalOf back; + /// @brief A normalized right-oriented vector + const static SphericalOf right; + /// @brief A normalized left-oriented vector + const static SphericalOf left; + /// @brief A normalized up-oriented vector + const static SphericalOf up; + /// @brief A normalized down-oriented vector + const static SphericalOf down; + + /// @brief Negate the vector + /// @return The negated vector + /// This will rotate the vector by 180 degrees horizontally and + /// vertically. Distance will stay the same. + SphericalOf operator-() const; + + /// @brief Subtract a spherical vector from this vector + /// @param v The vector to subtract + /// @return The result of the subtraction + SphericalOf operator-(const SphericalOf& v) const; + SphericalOf operator-=(const SphericalOf& v); + /// @brief Add a spherical vector to this vector + /// @param v The vector to add + /// @return The result of the addition + SphericalOf operator+(const SphericalOf& v) const; + SphericalOf operator+=(const SphericalOf& v); +}; + +using SphericalSingle = SphericalOf; +using Spherical16 = SphericalOf; + /// @brief A spherical vector /// @details This is a vector in 3D space using a spherical coordinate system. /// It consists of a distance and the polar and elevation angles from a diff --git a/Spherical16.cpp b/Spherical16.cpp index 5000841..d9f0c8c 100644 --- a/Spherical16.cpp +++ b/Spherical16.cpp @@ -1,3 +1,4 @@ +/* #include "Spherical16.h" #include "Quaternion.h" @@ -44,6 +45,24 @@ Spherical16::Spherical16(Vector3 v) { } } +Vector3 Passer::LinearAlgebra::Spherical16::ToVector3() { + float verticalRad = + (90.0f - this->verticalAngle.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; + float horizontalRad = + this->horizontalAngle.ToFloat() * Passer::LinearAlgebra::Deg2Rad; + float cosVertical = cosf(verticalRad); + float sinVertical = sinf(verticalRad); + float cosHorizontal = cosf(horizontalRad); + float sinHorizontal = sinf(horizontalRad); + + float x = this->distance * sinVertical * sinHorizontal; + float y = this->distance * cosVertical; + float z = this->distance * sinVertical * cosHorizontal; + + Vector3 v = Vector3(x, y, z); + return Vector3(); +} + const Spherical16 Spherical16::zero = Spherical16(0.0f, 0.0f, 0.0f); const Spherical16 Spherical16::forward = Spherical16(1.0f, 0.0f, 0.0f); const Spherical16 Spherical16::back = Spherical16(1.0f, 180.0f, 0.0f); @@ -103,7 +122,7 @@ Spherical16 Spherical16::operator+(const Spherical16& s2) const { Vector3 v = v1 + v2; Spherical16 r = Spherical16(v); return r; - /* + // This is the hard way... if (v2.distance <= 0) return Spherical(this->distance, this->horizontalAngle, @@ -148,7 +167,7 @@ Spherical16 Spherical16::operator+(const Spherical16& s2) const { : Angle::Normalize(this->verticalAngle + verticalAngle); Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); - */ + } Spherical16 Spherical16::operator+=(const Spherical16& v) { *this = *this + v; @@ -234,4 +253,5 @@ Spherical16 Spherical16::RotateVertical(const Spherical16& v, Angle a) { Spherical16 r = Spherical16(v.distance, v.horizontalAngle, v.verticalAngle.ToFloat() + a.ToFloat()); return r; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/Spherical16.h b/Spherical16.h index 1f9f448..803d179 100644 --- a/Spherical16.h +++ b/Spherical16.h @@ -1,3 +1,4 @@ +/* // 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/. @@ -48,6 +49,8 @@ struct Spherical16 { /// @param v Vector in 3D carthesian coordinates; Spherical16(Vector3 v); + Vector3 ToVector3(); + /// @brief A spherical vector with zero degree angles and distance const static Spherical16 zero; /// @brief A normalized forward-oriented vector @@ -155,4 +158,5 @@ using namespace Passer::LinearAlgebra; #include "Vector3.h" -#endif \ No newline at end of file +#endif +*/ \ No newline at end of file From 1da93cac156d136db5097e49e12d1d09c20f0313 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 22 Aug 2024 12:49:46 +0200 Subject: [PATCH 073/121] Fix ToVector3 --- Spherical.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spherical.cpp b/Spherical.cpp index dca766b..bbf8d28 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -76,7 +76,7 @@ Vector3 SphericalOf::ToVector3() const { float z = this->distance * sinVertical * cosHorizontal; Vector3 v = Vector3(x, y, z); - return Vector3(); + return v; } template From dedaa31740c4674b127f4a8c5298cb4a0783ec16 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 22 Aug 2024 14:24:33 +0200 Subject: [PATCH 074/121] Fix unit tests --- Angle.cpp | 19 +++--- Angle.h | 3 - Spherical.cpp | 9 +++ Spherical.h | 2 + test/Spherical16_test.cc | 121 ++++++++++++++++++--------------------- 5 files changed, 77 insertions(+), 77 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 4948086..536f719 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -6,10 +6,9 @@ #include #include "FloatSingle.h" +const float Rad2Deg = 57.29578F; +const float Deg2Rad = 0.0174532924F; /* -const float Angle::Rad2Deg = 57.29578F; -const float Angle::Deg2Rad = 0.0174532924F; - float Angle::Normalize(float angle) { if (!isfinite(angle)) return angle; @@ -128,17 +127,17 @@ AngleOf AngleOf::operator+=(const AngleOf& a) { return *this; } -template <> -AngleOf AngleOf::Normalize(AngleOf angle) { +template +AngleOf AngleOf::Normalize(AngleOf angle) { float angleValue = angle.ToFloat(); if (!isfinite(angleValue)) - return angleValue; + return angle; while (angleValue <= -180) angleValue += 360; while (angleValue > 180) angleValue -= 360; - return angleValue; + return AngleOf(angleValue); } template <> @@ -194,8 +193,7 @@ AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { if (d <= -1) return 180.0f; - float rad2deg = Passer::LinearAlgebra::Rad2Deg; - float gamma = acosf(d) * rad2deg; + float gamma = acosf(d) * Rad2Deg; return gamma; } @@ -203,9 +201,10 @@ template <> AngleOf AngleOf::SineRuleAngle(float a, AngleOf beta, float b) { - float deg2rad = Passer::LinearAlgebra::Deg2Rad; + float deg2rad = Deg2Rad; float alpha = asinf(a * sinf(beta.ToFloat() * deg2rad) / b); return alpha; } + template class AngleOf; template class AngleOf; diff --git a/Angle.h b/Angle.h index 37c2758..c1d81a1 100644 --- a/Angle.h +++ b/Angle.h @@ -25,9 +25,6 @@ class AngleOf { inline T GetBinary() const { return this->value; } - static AngleOf Rad2Deg; - static AngleOf Deg2Rad; - static AngleOf pi; bool operator==(AngleOf a); diff --git a/Spherical.cpp b/Spherical.cpp index bbf8d28..744b654 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -46,6 +46,15 @@ SphericalOf::SphericalOf(float distance, // this->vertical = vertical; // } +template <> +SphericalOf SphericalOf::FromPolar(Polar polar) { + AngleOf horizontal = polar.angle; + AngleOf vertical = AngleOf(0); + SphericalOf r = + SphericalOf(polar.distance, horizontal, vertical); + return r; +} + template SphericalOf SphericalOf::FromVector3(Vector3 v) { float distance = v.magnitude(); diff --git a/Spherical.h b/Spherical.h index 37799df..47c14bc 100644 --- a/Spherical.h +++ b/Spherical.h @@ -29,6 +29,8 @@ class SphericalOf { SphericalOf(); SphericalOf(float distance, AngleOf horizontal, AngleOf vertical); + static SphericalOf FromPolar(Polar v); + static SphericalOf FromVector3(Vector3 v); Vector3 ToVector3() const; diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index 4f6f5e1..88f6d0b 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -3,82 +3,80 @@ #include #include -#include "Spherical16.h" +#include "Spherical.h" #define FLOAT_INFINITY std::numeric_limits::infinity() TEST(Spherical16, FromVector3) { Vector3 v = Vector3(0, 0, 1); - Spherical16 s = Spherical16(v); + Spherical16 s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ((float)s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ((float)s.verticalAngle.ToFloat(), 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ((float)s.horizontal.ToFloat(), 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ((float)s.vertical.ToFloat(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); - s = Spherical16(v); + s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); - s = Spherical16(v); + s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 1 0 0"; } -TEST(Spherical16, FromPolar) { - Polar p = Polar(1, 0); - Spherical16 s = Spherical16(p); +// TEST(Spherical16, FromPolar) { +// Polar p = Polar(1, 0); +// Spherical16 s = Spherical16::FromPolar(p); - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; +// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; +// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; +// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; - p = Polar(1, 45); - s = Spherical16(p); +// p = Polar(1, 45); +// s = Spherical16::FromPolar(p); - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; +// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; +// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; +// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; - p = Polar(1, -45); - s = Spherical16(p); +// p = Polar(1, -45); +// s = Spherical16::FromPolar(p); - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; +// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; +// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; +// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; - p = Polar(0, 0); - s = Spherical16(p); +// p = Polar(0, 0); +// s = Spherical16::FromPolar(p); - EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; +// EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; +// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; +// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; - p = Polar(-1, 0); - s = Spherical16(p); +// p = Polar(-1, 0); +// s = Spherical16::FromPolar(p); - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), -180.0F) << "s.hor Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; -} +// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; +// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -180.0F) << "s.hor Polar(-1 0)"; +// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; +// } TEST(Spherical16, Incident1) { Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); - Spherical16 s = Spherical16(v); + Spherical16 s = Spherical16::FromVector3(v); Spherical16 sr = Spherical16(2.49F, 98.18f, 24.4F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), - 1.0e-02); - EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-02); + EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-02); + EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-02); - Vector3 r = Vector3(Spherical(sr.distance, sr.horizontalAngle.ToFloat(), - sr.verticalAngle.ToFloat())); + Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0"; EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0"; @@ -86,43 +84,38 @@ TEST(Spherical16, Incident1) { TEST(Spherical16, Incident2) { Vector3 v = Vector3(1.0f, 0.0f, 1.0f); - Spherical16 s = Spherical16(v); + Spherical16 s = Spherical16::FromVector3(v); Spherical16 sr = Spherical16(1.4142135623F, 45.0f, 0.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), - 1.0e-05); - EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); - Vector3 r = Vector3(Spherical(sr.distance, sr.horizontalAngle.ToFloat(), - sr.verticalAngle.ToFloat())); + Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(0.0f, 1.0f, 1.0f); - s = Spherical16(v); + s = Spherical16::FromVector3(v); sr = Spherical16(1.4142135623F, 0.0f, 45.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), - 1.0e-05); - EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); - r = Vector3(Spherical(sr.distance, sr.horizontalAngle.ToFloat(), - sr.verticalAngle.ToFloat())); + r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); - s = Spherical16(v); - r = Vector3(Spherical(s.distance, s.horizontalAngle.ToFloat(), - s.verticalAngle.ToFloat())); + s = Spherical16::FromVector3(v); + r = Spherical16(s.distance, s.horizontal, s.vertical).ToVector3(); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), 45.0F, 1.0e-02); - EXPECT_NEAR(s.verticalAngle.ToFloat(), 35.26F, 1.0e-02); + EXPECT_NEAR(s.horizontal.ToFloat(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.vertical.ToFloat(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-04); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-04); @@ -150,14 +143,14 @@ TEST(Spherical16, Addition) { v2 = Spherical16(1, -45, 0); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 0) << "Addition(1 -45 0)"; v2 = Spherical16(1, 0, 90); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file From e10e0100955f8f4dd139f52d71e37d6ace8c5fc0 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 22 Aug 2024 14:35:37 +0200 Subject: [PATCH 075/121] Added Direction to library sources --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2df11da..cc51cb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ else() "Matrix.cpp" "Axis.cpp" "AngleAxis.cpp" + "Direction.cpp" ) enable_testing() From b460bec6969fbcd160cf5f995974e2164b491f12 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 28 Aug 2024 09:18:50 +0200 Subject: [PATCH 076/121] Added scaling to SphericalOf --- Spherical.cpp | 12 ++++++++++++ Spherical.h | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Spherical.cpp b/Spherical.cpp index 744b654..69e2d9f 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -192,6 +192,18 @@ SphericalOf SphericalOf::operator+=(const SphericalOf& v) { return *this; } +template +SphericalOf SphericalOf::operator*=(float f) { + this->distance *= f; + return *this; +} + +template +SphericalOf SphericalOf::operator/=(float f) { + this->distance /= f; + return *this; +} + template class SphericalOf; template class SphericalOf; diff --git a/Spherical.h b/Spherical.h index 47c14bc..3926b5d 100644 --- a/Spherical.h +++ b/Spherical.h @@ -65,6 +65,33 @@ class SphericalOf { /// @return The result of the addition SphericalOf operator+(const SphericalOf& v) const; SphericalOf operator+=(const SphericalOf& v); + + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend SphericalOf operator*(const SphericalOf& v, float f) { + return SphericalOf(v.distance * f, v.horizontal, v.vertical); + } + friend SphericalOf operator*(float f, const SphericalOf& v) { + return SphericalOf(v.distance * f, v.horizontal, + v.vertical); // not correct, should be f * v.distance + } + SphericalOf operator*=(float f); + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled factor + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend SphericalOf operator/(const SphericalOf& v, float f) { + return SphericalOf(v.distance / f, v.horizontal, v.vertical); + } + friend SphericalOf operator/(float f, const SphericalOf& v) { + return SphericalOf(v.distance / f, v.horizontal, + v.vertical); // not correct, should be f / v.distance + } + SphericalOf operator/=(float f); }; using SphericalSingle = SphericalOf; From f48343952bf4b3ae97aeba437143ce8b2a6e5fa5 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 28 Aug 2024 11:32:37 +0200 Subject: [PATCH 077/121] Moved Polar/Spherical to template class completely --- Polar.cpp | 156 ++++++++++++++++++++++++++++++++++++++- Polar.h | 126 ++++++++++++++++++++++++++++++- Spherical.cpp | 105 +++++++++++++------------- Spherical.h | 13 +++- Vector2.h | 6 +- Vector3.cpp | 5 +- Vector3.h | 6 +- test/Polar_test.cc | 19 ++--- test/Spherical16_test.cc | 1 + test/Spherical_test.cc | 83 ++++++++++----------- test/Vector2_test.cc | 8 +- test/Vector3_test.cc | 6 +- 12 files changed, 407 insertions(+), 127 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index b3f09e8..cc86cca 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -1,9 +1,155 @@ #include -#include "Angle.h" #include "Polar.h" -#include "Spherical.h" +template +PolarOf::PolarOf() { + this->distance = 0.0f; + this->angle = 0.0f; +} +template +PolarOf::PolarOf(float distance, AngleOf angle) { + // distance should always be 0 or greater + if (distance < 0.0f) { + this->distance = -distance; + this->angle = AngleOf::Normalize(angle.ToFloat() - 180.0f); + } else { + this->distance = distance; + if (this->distance == 0.0f) + // angle is always 0 if distance is 0 + this->angle = 0.0f; + else + this->angle = AngleOf::Normalize(angle); + } +} + +template +PolarOf PolarOf::FromVector2(Vector2 v) { + float distance = v.magnitude(); + AngleOf angle = Vector2::SignedAngle(Vector2::forward, v); + PolarOf p = PolarOf(distance, angle); + return p; +} +template +PolarOf PolarOf::FromSpherical(SphericalOf v) { + float distance = + v.distance * cosf(v.vertical.ToFloat() * Passer::LinearAlgebra::Deg2Rad); + AngleOf angle = v.horizontal; + PolarOf p = PolarOf(distance, angle); + return p; +} + +template +const PolarOf PolarOf::zero = PolarOf(0.0f, 0.0f); +template +const PolarOf PolarOf::forward = PolarOf(1.0f, 0.0f); +template +const PolarOf PolarOf::back = PolarOf(1.0, 180.0f); +template +const PolarOf PolarOf::right = PolarOf(1.0, 90.0f); +template +const PolarOf PolarOf::left = PolarOf(1.0, -90.0f); + +template +bool PolarOf::operator==(const PolarOf& v) const { + return (this->distance == v.distance && + this->angle.ToFloat() == v.angle.ToFloat()); +} + +template +PolarOf PolarOf::Normalize(const PolarOf& v) { + PolarOf r = PolarOf(1, v.angle); + return r; +} +template +PolarOf PolarOf::normalized() const { + PolarOf r = PolarOf(1, this->angle); + return r; +} + +template +PolarOf PolarOf::operator-() const { + PolarOf v = PolarOf(this->distance, this->angle + AngleOf(180)); + return v; +} + +template +PolarOf PolarOf::operator-(const PolarOf& v) const { + PolarOf r = -v; + return *this + r; +} +template +PolarOf PolarOf::operator-=(const PolarOf& v) { + *this = *this - v; + return *this; +} + +template +PolarOf PolarOf::operator+(const PolarOf& v) const { + if (v.distance == 0) + return PolarOf(this->distance, this->angle); + if (this->distance == 0.0f) + return v; + + float deltaAngle = + Angle::Normalize(v.angle.ToFloat() - this->angle.ToFloat()).ToFloat(); + float rotation = + deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle; + + if (rotation == 180.0f && v.distance > 0.0f) { + // angle is too small, take this angle and add the distances + return PolarOf(this->distance + v.distance, this->angle); + } + + float newDistance = + Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat(); + + float angle = + Angle::CosineRuleAngle(newDistance, this->distance, v.distance).ToFloat(); + + float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle + : this->angle.ToFloat() + angle; + newAngle = Angle::Normalize(newAngle).ToFloat(); + PolarOf vector = PolarOf(newDistance, newAngle); + return vector; +} +template +PolarOf PolarOf::operator+=(const PolarOf& v) { + *this = *this + v; + return *this; +} + +template +PolarOf PolarOf::operator*=(float f) { + this->distance *= f; + return *this; +} +template +PolarOf PolarOf::operator/=(float f) { + this->distance /= f; + return *this; +} + +template +float PolarOf::Distance(const PolarOf& v1, const PolarOf& v2) { + float d = Angle::CosineRuleSide(v1.distance, v2.distance, + v2.angle.ToFloat() - v1.angle.ToFloat()) + .ToFloat(); + return d; +} + +template +PolarOf PolarOf::Rotate(const PolarOf& v, AngleOf angle) { + AngleOf a = AngleOf::Normalize(v.angle + angle); + PolarOf r = PolarOf(v.distance, a); + return r; +} + +template class PolarOf; +template class PolarOf; + +//===================================== +/* Polar::Polar() { this->distance = 0.0f; this->angle = 0.0f; @@ -85,7 +231,8 @@ Polar Polar::operator+(const Polar& v) const { Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat(); float angle = - Angle::CosineRuleAngle(newDistance, this->distance, v.distance).ToFloat(); + Angle::CosineRuleAngle(newDistance, this->distance, +v.distance).ToFloat(); float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle : this->angle.ToFloat() + angle; @@ -130,4 +277,5 @@ Polar Polar::Rotate(const Polar& v, Angle angle) { Angle a = Angle::Normalize(v.angle.ToFloat() + angle.ToFloat()); Polar r = Polar(v.distance, a); return r; -} \ No newline at end of file +} +*/ diff --git a/Polar.h b/Polar.h index d6eb5ff..3264880 100644 --- a/Polar.h +++ b/Polar.h @@ -11,8 +11,130 @@ namespace Passer { namespace LinearAlgebra { struct Vector2; -struct Spherical; +template +class SphericalOf; +template +class PolarOf { + public: + /// @brief The distance in meters + /// @remark The distance shall never be negative + float distance; + /// @brief The angle in degrees clockwise rotation + /// @remark The angle shall be between -180 .. 180 + AngleOf angle; + + /// @brief A new vector with polar coordinates with zero degrees and + /// distance + PolarOf(); + /// @brief A new vector with polar coordinates + /// @param distance The distance in meters + /// @param angle The angle in degrees, clockwise rotation + /// @note The distance is automatically converted to a positive value. + /// @note The angle is automatically normalized to -180 .. 180 + PolarOf(float distance, AngleOf angle); + /// @brief Convert a vector from 2D carthesian coordinates to polar + /// coordinates + /// @param v The vector to convert + static PolarOf FromVector2(Vector2 v); + /// @brief Convert a vector from spherical coordinates to polar coordinates + /// @param s The vector to convert + /// @note The resulting vector will be projected on the horizontal plane + static PolarOf FromSpherical(SphericalOf v); + + /// @brief A polar vector with zero degrees and distance + const static PolarOf zero; + /// @brief A normalized forward-oriented vector + const static PolarOf forward; + /// @brief A normalized back-oriented vector + const static PolarOf back; + /// @brief A normalized right-oriented vector + const static PolarOf right; + /// @brief A normalized left-oriented vector + const static PolarOf left; + + /// @brief Equality test to another vector + /// @param v The vector to check against + /// @return true: if it is identical to the given vector + /// @note This uses float comparison to check equality which may have + /// strange effects. Equality on floats should be avoided. + bool operator==(const PolarOf& v) const; + + /// @brief The vector length + /// @param v The vector for which you need the length + /// @return The vector length; + inline static float Magnitude(const PolarOf& v) { return v.distance; } + /// @brief The vector length + /// @return The vector length + inline float magnitude() const { return this->distance; } + + /// @brief Convert the vector to a length of 1 + /// @param v The vector to convert + /// @return The vector normalized to a length of 1 + static PolarOf Normalize(const PolarOf& v); + /// @brief Convert the vector to a length of a + /// @return The vector normalized to a length of 1 + PolarOf normalized() const; + + /// @brief Negate the vector + /// @return The negated vector + /// This will rotate the vector by 180 degrees. Distance will stay the same. + PolarOf operator-() const; + + /// @brief Subtract a polar vector from this vector + /// @param v The vector to subtract + /// @return The result of the subtraction + PolarOf operator-(const PolarOf& v) const; + PolarOf operator-=(const PolarOf& v); + /// @brief Add a polar vector to this vector + /// @param v The vector to add + /// @return The result of the addition + PolarOf operator+(const PolarOf& v) const; + PolarOf operator+=(const PolarOf& v); + + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend PolarOf operator*(const PolarOf& v, float f) { + return PolarOf(v.distance * f, v.angle); + } + friend PolarOf operator*(float f, const PolarOf& v) { + return PolarOf(f * v.distance, v.angle); + } + PolarOf operator*=(float f); + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled factor + /// @remark This operation will scale the distance of the vector. The angle + /// will be unaffected. + friend PolarOf operator/(const PolarOf& v, float f) { + return PolarOf(v.distance / f, v.angle); + } + friend PolarOf operator/(float f, const PolarOf& v) { + return PolarOf(f / v.distance, v.angle); + } + PolarOf operator/=(float f); + + /// @brief The distance between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The distance between the two vectors + static float Distance(const PolarOf& v1, const PolarOf& v2); + + /// @brief Rotate a vector + /// @param v The vector to rotate + /// @param a The angle in degreesto rotate + /// @return The rotated vector + static PolarOf Rotate(const PolarOf& v, AngleOf a); +}; + +using PolarSingle = PolarOf; +using Polar16 = PolarOf; +using Polar = PolarSingle; + +/* /// @brief A polar vector /// @details This will use the polar coordinate system consisting of a angle /// from a reference direction and a distance. @@ -130,6 +252,8 @@ struct Polar { /// @return The rotated vector static Polar Rotate(const Polar& v, Angle a); }; +*/ + } // namespace LinearAlgebra } // namespace Passer using namespace Passer::LinearAlgebra; diff --git a/Spherical.cpp b/Spherical.cpp index 69e2d9f..92efeb9 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -46,12 +46,11 @@ SphericalOf::SphericalOf(float distance, // this->vertical = vertical; // } -template <> -SphericalOf SphericalOf::FromPolar(Polar polar) { - AngleOf horizontal = polar.angle; - AngleOf vertical = AngleOf(0); - SphericalOf r = - SphericalOf(polar.distance, horizontal, vertical); +template +SphericalOf SphericalOf::FromPolar(PolarOf polar) { + AngleOf horizontal = polar.angle; + AngleOf vertical = AngleOf(0); + SphericalOf r = SphericalOf(polar.distance, horizontal, vertical); return r; } @@ -208,18 +207,18 @@ template class SphericalOf; template class SphericalOf; //--------------------------------------- - +/* Spherical::Spherical() { this->distance = 0.0f; this->horizontalAngle = 0.0f; this->verticalAngle = 0.0f; } -Spherical::Spherical(Polar polar) { - this->distance = polar.distance; - this->horizontalAngle = polar.angle; - this->verticalAngle = 0.0f; -} +// Spherical::Spherical(Polar polar) { +// this->distance = polar.distance; +// this->horizontalAngle = polar.angle; +// this->verticalAngle = 0.0f; +// } Spherical::Spherical(float distance, Angle horizontalAngle, @@ -299,52 +298,53 @@ Spherical Spherical::operator+(const Spherical& s2) const { Vector3 v = v1 + v2; Spherical r = Spherical(v); return r; - /* + // This is the hard way... - if (v2.distance <= 0) - return Spherical(this->distance, this->horizontalAngle, - this->verticalAngle); - if (this->distance <= 0) - return v2; + // if (v2.distance <= 0) + // return Spherical(this->distance, this->horizontalAngle, + // this->verticalAngle); + // if (this->distance <= 0) + // return v2; - float deltaHorizontalAngle = - (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); - float horizontalRotation = deltaHorizontalAngle < 0 - ? 180 + deltaHorizontalAngle - : 180 - deltaHorizontalAngle; - float deltaVerticalAngle = - Angle::Normalize(v2.verticalAngle - this->verticalAngle); - float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle - : 180 - deltaVerticalAngle; + // float deltaHorizontalAngle = + // (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); + // float horizontalRotation = deltaHorizontalAngle < 0 + // ? 180 + deltaHorizontalAngle + // : 180 - deltaHorizontalAngle; + // float deltaVerticalAngle = + // Angle::Normalize(v2.verticalAngle - this->verticalAngle); + // float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle + // : 180 - deltaVerticalAngle; - if (horizontalRotation == 180 && verticalRotation == 180) - // angle is too small, take this angle and add the distances - return Spherical(this->distance + v2.distance, this->horizontalAngle, - this->verticalAngle); + // if (horizontalRotation == 180 && verticalRotation == 180) + // // angle is too small, take this angle and add the distances + // return Spherical(this->distance + v2.distance, this->horizontalAngle, + // this->verticalAngle); - Angle rotation = AngleBetween(*this, v2); - float newDistance = - Angle::CosineRuleSide(v2.distance, this->distance, rotation); - float angle = - Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); + // Angle rotation = AngleBetween(*this, v2); + // float newDistance = + // Angle::CosineRuleSide(v2.distance, this->distance, rotation); + // float angle = + // Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); - // Now we have to project the angle to the horizontal and vertical planes... - // The axis for the angle is the cross product of the two spherical vectors - // (which function we do not have either...) - float horizontalAngle = 0; - float verticalAngle = 0; + // // Now we have to project the angle to the horizontal and vertical +planes... + // // The axis for the angle is the cross product of the two spherical vectors + // // (which function we do not have either...) + // float horizontalAngle = 0; + // float verticalAngle = 0; - float newHorizontalAngle = - deltaHorizontalAngle < 0 - ? Angle::Normalize(this->horizontalAngle - horizontalAngle) - : Angle::Normalize(this->horizontalAngle + horizontalAngle); - float newVerticalAngle = - deltaVerticalAngle < 0 - ? Angle::Normalize(this->verticalAngle - verticalAngle) - : Angle::Normalize(this->verticalAngle + verticalAngle); + // float newHorizontalAngle = + // deltaHorizontalAngle < 0 + // ? Angle::Normalize(this->horizontalAngle - horizontalAngle) + // : Angle::Normalize(this->horizontalAngle + horizontalAngle); + // float newVerticalAngle = + // deltaVerticalAngle < 0 + // ? Angle::Normalize(this->verticalAngle - verticalAngle) + // : Angle::Normalize(this->verticalAngle + verticalAngle); + + // Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); - Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); - */ } Spherical Spherical::operator+=(const Spherical& v) { *this = *this + v; @@ -428,4 +428,5 @@ Spherical Spherical::RotateVertical(const Spherical& v, Angle a) { Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat(), v.verticalAngle.ToFloat() + a.ToFloat()); return r; -} \ No newline at end of file +} +*/ diff --git a/Spherical.h b/Spherical.h index 3926b5d..06956ec 100644 --- a/Spherical.h +++ b/Spherical.h @@ -6,12 +6,14 @@ #define SPHERICAL_H #include "Angle.h" -#include "Polar.h" +// #include "Polar.h" namespace Passer { namespace LinearAlgebra { struct Vector3; +template +class PolarOf; template class SphericalOf { @@ -29,7 +31,7 @@ class SphericalOf { SphericalOf(); SphericalOf(float distance, AngleOf horizontal, AngleOf vertical); - static SphericalOf FromPolar(Polar v); + static SphericalOf FromPolar(PolarOf v); static SphericalOf FromVector3(Vector3 v); Vector3 ToVector3() const; @@ -96,7 +98,8 @@ class SphericalOf { using SphericalSingle = SphericalOf; using Spherical16 = SphericalOf; - +using Spherical = SphericalSingle; +/* /// @brief A spherical vector /// @details This is a vector in 3D space using a spherical coordinate system. /// It consists of a distance and the polar and elevation angles from a @@ -125,7 +128,7 @@ struct Spherical { Spherical(float distance, Angle horizontalAngle, Angle verticalAngle); /// @brief Convert polar coordinates to spherical coordinates /// @param polar The polar coordinate - Spherical(Polar polar); + // Spherical(Polar polar); /// @brief Convert 3D carthesian coordinates to spherical coordinates /// @param v Vector in 3D carthesian coordinates; Spherical(Vector3 v); @@ -228,11 +231,13 @@ struct Spherical { static Spherical RotateHorizontal(const Spherical& v, Angle angle); static Spherical RotateVertical(const Spherical& v, Angle angle); }; +*/ } // namespace LinearAlgebra } // namespace Passer using namespace Passer::LinearAlgebra; +#include "Polar.h" #include "Vector3.h" #endif \ No newline at end of file diff --git a/Vector2.h b/Vector2.h index c4abf6c..7805e69 100644 --- a/Vector2.h +++ b/Vector2.h @@ -30,7 +30,9 @@ namespace Passer { namespace LinearAlgebra { struct Vector3; -struct Polar; +template +class PolarOf; +// using Polar = PolarOf /// @brief A 2=dimensional vector /// @remark This uses the right=handed carthesian coordinate system. @@ -51,7 +53,7 @@ struct Vector2 : Vec2 { Vector2(Vector3 v); /// @brief Convert a Polar vector to a 2-dimensional vector /// @param v The vector in polar coordinates - Vector2(Polar v); + Vector2(PolarOf v); /// @brief Vector2 destructor ~Vector2(); diff --git a/Vector3.cpp b/Vector3.cpp index 36c2b3b..4f5a95b 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -32,9 +32,8 @@ Vector3::Vector3(Vector2 v) { Vector3::Vector3(Spherical s) { float verticalRad = - (90.0f - s.verticalAngle.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; - float horizontalRad = - s.horizontalAngle.ToFloat() * Passer::LinearAlgebra::Deg2Rad; + (90.0f - s.vertical.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; + float horizontalRad = s.horizontal.ToFloat() * Passer::LinearAlgebra::Deg2Rad; float cosVertical = cosf(verticalRad); float sinVertical = sinf(verticalRad); float cosHorizontal = cosf(horizontalRad); diff --git a/Vector3.h b/Vector3.h index 4f8aa1d..b480d20 100644 --- a/Vector3.h +++ b/Vector3.h @@ -10,7 +10,9 @@ namespace Passer { namespace LinearAlgebra { -struct Spherical; +// struct Spherical; +template +class SphericalOf; extern "C" { /// @@ -56,7 +58,7 @@ struct Vector3 : Vec3 { /// @brief Convert vector in spherical coordinates to 3d carthesian /// coordinates /// @param v The vector to convert - Vector3(Spherical v); + Vector3(SphericalOf v); /// @brief Vector3 destructor ~Vector3(); diff --git a/test/Polar_test.cc b/test/Polar_test.cc index c548d0f..4f28c17 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -4,24 +4,25 @@ #include #include "Polar.h" +#include "Spherical.h" #define FLOAT_INFINITY std::numeric_limits::infinity() TEST(Polar, FromVector2) { Vector2 v = Vector2(0, 1); - Polar p = Polar(v); + Polar p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "s.angle 0 0 1"; v = Vector2(1, 0); - p = Polar(v); + p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), 90.0F) << "s.angle 1 0"; v = Vector2(-1, 1); - p = Polar(v); + p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1"; EXPECT_NEAR(p.angle.ToFloat(), -45.0F, 1.0e-05) << "s.angle -1 1"; @@ -32,38 +33,38 @@ TEST(Polar, FromSpherical) { Polar p; s = Spherical(1, 0, 0); - p = Polar(s); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(1 0 0)"; s = Spherical(1, 45, 0); - p = Polar(s); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), 45.0F) << "p.angle FromSpherical(1 45 0)"; s = Spherical(1, -45, 0); - p = Polar(s); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), -45.0F) << "p.angle FromSpherical(1 -45 0)"; s = Spherical(0, 0, 0); - p = Polar(s); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 0)"; s = Spherical(-1, 0, 0); - p = Polar(s); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), 180.0F) << "p.angle FromSpherical(-1 0 0)"; s = Spherical(0, 0, 90); - p = Polar(s); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)"; EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 90)"; diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index 88f6d0b..677c383 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -4,6 +4,7 @@ #include #include "Spherical.h" +#include "Vector3.h" #define FLOAT_INFINITY std::numeric_limits::infinity() diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 9d963aa..df338d1 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -9,73 +9,72 @@ TEST(Spherical, FromVector3) { Vector3 v = Vector3(0, 0, 1); - Spherical s = Spherical(v); + Spherical s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); - s = Spherical(v); + s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); - s = Spherical(v); + s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 1 0 0"; } TEST(Spherical, FromPolar) { Polar p = Polar(1, 0); - Spherical s = Spherical(p); + Spherical s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; p = Polar(1, 45); - s = Spherical(p); + s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; p = Polar(1, -45); - s = Spherical(p); + s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; p = Polar(0, 0); - s = Spherical(p); + s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; p = Polar(-1, 0); - s = Spherical(p); + s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 180.0F) << "s.hor Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 180.0F) << "s.hor Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; } TEST(Spherical, Incident1) { Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); - Spherical s = Spherical(v); + Spherical s = Spherical::FromVector3(v); Spherical sr = Spherical(2.49F, 98.18f, 24.4F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), - 1.0e-02); - EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-02); + EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-02); + EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-02); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; @@ -85,13 +84,12 @@ TEST(Spherical, Incident1) { TEST(Spherical, Incident2) { Vector3 v = Vector3(1.0f, 0.0f, 1.0f); - Spherical s = Spherical(v); + Spherical s = Spherical::FromVector3(v); Spherical sr = Spherical(1.4142135623F, 45.0f, 0.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), - 1.0e-05); - EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -99,13 +97,12 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(0.0f, 1.0f, 1.0f); - s = Spherical(v); + s = Spherical::FromVector3(v); sr = Spherical(1.4142135623F, 0.0f, 45.0F); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(), - 1.0e-05); - EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -113,12 +110,12 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); - s = Spherical(v); + s = Spherical::FromVector3(v); r = Vector3(s); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontalAngle.ToFloat(), 45.0F, 1.0e-02); - EXPECT_NEAR(s.verticalAngle.ToFloat(), 35.26F, 1.0e-02); + EXPECT_NEAR(s.horizontal.ToFloat(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.vertical.ToFloat(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); @@ -146,14 +143,14 @@ TEST(Spherical, Addition) { v2 = Spherical(1, -45, 0); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 0) << "Addition(1 -45 0)"; v2 = Spherical(1, 0, 90); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index ba61ec6..a7561f2 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Vector2.h" @@ -13,21 +13,21 @@ TEST(Vector2, FromPolar) { Vector2 r; v = Vector2(0, 1); - p = Polar(v); + p = Polar::FromVector2(v); r = Vector2(p); EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 1)"; EXPECT_FLOAT_EQ(r.y, 1.0F) << "FromPolar(0 1)"; v = Vector2(1, 0); - p = Polar(v); + p = Polar::FromVector2(v); r = Vector2(p); EXPECT_FLOAT_EQ(r.x, 1.0F) << "FromPolar(1 0)"; EXPECT_NEAR(r.y, 0.0F, 1.0e-07) << "FromPolar(1 0)"; v = Vector2(0, 0); - p = Polar(v); + p = Polar::FromVector2(v); r = Vector2(p); EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 0)"; diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index c7ba095..01170da 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -9,7 +9,7 @@ TEST(Vector3, FromSpherical) { Vector3 v = Vector3(0, 0, 1); - Spherical s = Spherical(v); + Spherical s = Spherical::FromVector3(v); Vector3 r = Vector3(s); EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 0 1"; @@ -17,7 +17,7 @@ TEST(Vector3, FromSpherical) { EXPECT_FLOAT_EQ(r.Forward(), 1.0F) << "toVector3.z 0 0 1"; v = Vector3(0, 1, 0); - s = Spherical(v); + s = Spherical::FromVector3(v); r = Vector3(s); EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 1 0"; @@ -25,7 +25,7 @@ TEST(Vector3, FromSpherical) { EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; v = Vector3(1, 0, 0); - s = Spherical(v); + s = Spherical::FromVector3(v); r = Vector3(s); EXPECT_FLOAT_EQ(r.Right(), 1.0F) << "toVector3.x 1 0 0"; From b975aedd2b656077ee9b588a6c57ac8d9d2a55d7 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 28 Aug 2024 12:09:12 +0200 Subject: [PATCH 078/121] Added angle and rotate functions --- Spherical.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ Spherical.h | 19 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/Spherical.cpp b/Spherical.cpp index 92efeb9..5dabd01 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -203,6 +203,51 @@ SphericalOf SphericalOf::operator/=(float f) { return *this; } +#include "FloatSingle.h" +#include "Vector3.h" + +const float epsilon = 1E-05f; + +template +AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, + const SphericalOf& v2) { + float denominator = v1.distance * v2.distance; + if (denominator < epsilon) + return 0.0f; + + Vector3 v1_3 = v1.ToVector3(); + Vector3 v2_3 = v2.ToVector3(); + float dot = Vector3::Dot(v1_3, v2_3); + float fraction = dot / denominator; + if (isnan(fraction)) + return fraction; // short cut to returning NaN universally + + float cdot = Float::Clamp(fraction, -1.0, 1.0); + float r = ((float)acos(cdot)) * Rad2Deg; + return r; +} + +template +SphericalOf SphericalOf::Rotate(const SphericalOf& v, + AngleOf horizontalAngle, + AngleOf verticalAngle) { + SphericalOf r = SphericalOf(v.distance, v.horizontal + horizontalAngle, + v.vertical + verticalAngle); + return r; +} +template +SphericalOf SphericalOf::RotateHorizontal(const SphericalOf& v, + AngleOf a) { + SphericalOf r = SphericalOf(v.distance, v.horizontal + a, v.vertical); + return r; +} +template +SphericalOf SphericalOf::RotateVertical(const SphericalOf& v, + AngleOf a) { + SphericalOf r = SphericalOf(v.distance, v.horizontal, v.vertical + a); + return r; +} + template class SphericalOf; template class SphericalOf; diff --git a/Spherical.h b/Spherical.h index 06956ec..fa4b79f 100644 --- a/Spherical.h +++ b/Spherical.h @@ -94,6 +94,25 @@ class SphericalOf { v.vertical); // not correct, should be f / v.distance } SphericalOf operator/=(float f); + + /// + /// The distance between two vectors + /// + /// The first vector + /// The second vector + /// The distance between the two vectors + // static float Distance(const Spherical &s1, const Spherical &s2); + + static AngleOf AngleBetween(const SphericalOf& v1, + const SphericalOf& v2); + + static SphericalOf Rotate(const SphericalOf& v, + AngleOf horizontalAngle, + AngleOf verticalAngle); + static SphericalOf RotateHorizontal(const SphericalOf& v, + AngleOf angle); + static SphericalOf RotateVertical(const SphericalOf& v, + AngleOf angle); }; using SphericalSingle = SphericalOf; From b5a63305173bda457dea8f03cb878a642665dca0 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 28 Aug 2024 12:33:20 +0200 Subject: [PATCH 079/121] Fix anglebetween --- Spherical.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index 5dabd01..3f76c37 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -217,14 +217,15 @@ AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, Vector3 v1_3 = v1.ToVector3(); Vector3 v2_3 = v2.ToVector3(); - float dot = Vector3::Dot(v1_3, v2_3); - float fraction = dot / denominator; - if (isnan(fraction)) - return fraction; // short cut to returning NaN universally + // float dot = Vector3::Dot(v1_3, v2_3); + // float fraction = dot / denominator; + // if (isnan(fraction)) + // return fraction; // short cut to returning NaN universally - float cdot = Float::Clamp(fraction, -1.0, 1.0); - float r = ((float)acos(cdot)) * Rad2Deg; - return r; + // float cdot = Float::Clamp(fraction, -1.0, 1.0); + // float r = ((float)acos(cdot)) * Rad2Deg; + Angle r = Vector3::Angle(v1_3, v2_3); + return AngleOf(r.ToFloat()); } template From 6b3bcfc39195230fd37773b7c1047fd3ca9e3bc9 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 28 Aug 2024 12:35:46 +0200 Subject: [PATCH 080/121] Another anglebetween fix --- Spherical.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index 3f76c37..b4d6d07 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -211,9 +211,9 @@ const float epsilon = 1E-05f; template AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, const SphericalOf& v2) { - float denominator = v1.distance * v2.distance; - if (denominator < epsilon) - return 0.0f; + // float denominator = v1.distance * v2.distance; + // if (denominator < epsilon) + // return 0.0f; Vector3 v1_3 = v1.ToVector3(); Vector3 v2_3 = v2.ToVector3(); From 6a1d0434cf86136a7d739cf7d9b48d93dd6a1e66 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 6 Sep 2024 12:36:22 +0200 Subject: [PATCH 081/121] Added Angle comparison --- Angle.cpp | 26 +++++++++++++++++++++++--- Angle.h | 7 ++++++- test/Angle_test.cc | 28 ++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 536f719..f6cc704 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -96,9 +96,29 @@ float AngleOf::ToFloat() const { // template <> // AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; -template <> -bool AngleOf::operator==(AngleOf a) { - return this->ToFloat() == a.ToFloat(); +template +bool AngleOf::operator==(AngleOf a) { + return this->value == a.value; +} + +template +bool AngleOf::operator>(AngleOf a) { + return this->value > a.value; +} + +template +bool AngleOf::operator>=(AngleOf a) { + return this->value >= a.value; +} + +template +bool AngleOf::operator<(AngleOf a) { + return this->value < a.value; +} + +template +bool AngleOf::operator<=(AngleOf a) { + return this->value <= a.value; } template <> diff --git a/Angle.h b/Angle.h index c1d81a1..e02fcc3 100644 --- a/Angle.h +++ b/Angle.h @@ -28,6 +28,10 @@ class AngleOf { static AngleOf pi; bool operator==(AngleOf a); + bool operator>(AngleOf a); + bool operator>=(AngleOf a); + bool operator<(AngleOf a); + bool operator<=(AngleOf a); AngleOf operator-() const; AngleOf operator-(const AngleOf& a) const; @@ -61,7 +65,8 @@ class AngleOf { }; using Angle = AngleOf; -// using Angle = AngleOf; +using AngleSingle = AngleOf; +using Angle16 = AngleOf; } // namespace LinearAlgebra } // namespace Passer diff --git a/test/Angle_test.cc b/test/Angle_test.cc index 5625b2d..694ab62 100644 --- a/test/Angle_test.cc +++ b/test/Angle_test.cc @@ -8,6 +8,34 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() +TEST(Angle16, Compare) { + Angle16 a = Angle16(45); + bool r = false; + + r = a > Angle16(0); + EXPECT_TRUE(r) << "45 > 0"; + + r = a > Angle16(90); + EXPECT_FALSE(r) << "45 > 90"; + + r = a > Angle16(-90); + EXPECT_TRUE(r) << "45 > -90"; +} + +TEST(AngleSingle, Compare) { + AngleSingle a = AngleSingle(45); + bool r = false; + + r = a > AngleSingle(0); + EXPECT_TRUE(r) << "45 > 0"; + + r = a > AngleSingle(90); + EXPECT_FALSE(r) << "45 > 90"; + + r = a > AngleSingle(-90); + EXPECT_TRUE(r) << "45 > -90"; +} + TEST(Angle, Normalize) { Angle r = 0; From 05c61a3dbd3efd20cc2725da11f1314e63b7bd91 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 6 Sep 2024 13:16:49 +0200 Subject: [PATCH 082/121] Add distance between --- Spherical.cpp | 7 +++++++ Spherical.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/Spherical.cpp b/Spherical.cpp index b4d6d07..7f6c3ca 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -208,6 +208,13 @@ SphericalOf SphericalOf::operator/=(float f) { const float epsilon = 1E-05f; +template +float SphericalOf::DistanceBetween(const SphericalOf& v1, + const SphericalOf& v2) { + SphericalOf difference = v1 - v2; + return difference.distance; +} + template AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, const SphericalOf& v2) { diff --git a/Spherical.h b/Spherical.h index fa4b79f..2c4a12b 100644 --- a/Spherical.h +++ b/Spherical.h @@ -103,6 +103,8 @@ class SphericalOf { /// The distance between the two vectors // static float Distance(const Spherical &s1, const Spherical &s2); + static float DistanceBetween(const SphericalOf& v1, + const SphericalOf& v2); static AngleOf AngleBetween(const SphericalOf& v1, const SphericalOf& v2); From 5c3dfa66d34f0ac27cb1a64fccb88fad4de61897 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 6 Sep 2024 13:17:14 +0200 Subject: [PATCH 083/121] Adde degrees/readians and poc ACos --- Angle.cpp | 13 +++++++++++++ Angle.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/Angle.cpp b/Angle.cpp index f6cc704..d9b805b 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -87,6 +87,14 @@ template <> float AngleOf::ToFloat() const { return value; } +template +float AngleOf::InDegrees() const { + return this->ToFloat(); +} +template +float AngleOf::InRadians() const { + return this->ToFloat() * Deg2Rad; +} // template <> // AngleOf AngleOf::pi = 3.1415927410125732421875F; @@ -185,6 +193,11 @@ AngleOf AngleOf::MoveTowards(AngleOf fromAngle, return fromAngle.ToFloat() + d; } +template +float AngleOf::ACos(AngleOf a) { + return acosf(a.InRadians()); +} + template <> AngleOf AngleOf::CosineRuleSide(float a, float b, diff --git a/Angle.h b/Angle.h index e02fcc3..842b3e1 100644 --- a/Angle.h +++ b/Angle.h @@ -22,6 +22,8 @@ class AngleOf { // operator float() const; float ToFloat() const; + float InDegrees() const; + float InRadians() const; inline T GetBinary() const { return this->value; } @@ -55,6 +57,8 @@ class AngleOf { AngleOf toAngle, AngleOf maxAngle); + static float ACos(AngleOf); + static AngleOf CosineRuleSide(float a, float b, AngleOf gamma); static AngleOf CosineRuleAngle(float a, float b, float c); From 69bad8f66296ff85f397b1d02f9df9f1dd5bacc6 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 6 Sep 2024 15:35:39 +0200 Subject: [PATCH 084/121] Added degrees, radians, cos, sin, and tan functions --- Angle.cpp | 26 ++++++++++++++++++++------ Angle.h | 10 +++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index d9b805b..166a88e 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -78,10 +78,16 @@ AngleOf::AngleOf(int angle) : value((float)angle) {} template <> AngleOf::AngleOf(float angle) : value(angle) {} -// template <> -// AngleOf::operator float() const { -// return value; -// } +template +AngleOf AngleOf::Degrees(float a) { + AngleOf angle = AngleOf(a); + return angle; +} +template +AngleOf AngleOf::Radians(float a) { + AngleOf angle = AngleOf((a / pi) * 180); + return angle; +} template <> float AngleOf::ToFloat() const { @@ -194,8 +200,16 @@ AngleOf AngleOf::MoveTowards(AngleOf fromAngle, } template -float AngleOf::ACos(AngleOf a) { - return acosf(a.InRadians()); +float AngleOf::Cos(AngleOf a) { + return cosf(a.InRadians()); +} +template +float AngleOf::Sin(AngleOf a) { + return sinf(a.InRadians()); +} +template +float AngleOf::Tan(AngleOf a) { + return tanf(a.InRadians()); } template <> diff --git a/Angle.h b/Angle.h index 842b3e1..b65633b 100644 --- a/Angle.h +++ b/Angle.h @@ -19,7 +19,9 @@ class AngleOf { AngleOf() {}; AngleOf(int f); AngleOf(float f); - // operator float() const; + + static AngleOf Degrees(float f); + static AngleOf Radians(float f); float ToFloat() const; float InDegrees() const; @@ -27,7 +29,7 @@ class AngleOf { inline T GetBinary() const { return this->value; } - static AngleOf pi; + // static AngleOf pi; bool operator==(AngleOf a); bool operator>(AngleOf a); @@ -57,7 +59,9 @@ class AngleOf { AngleOf toAngle, AngleOf maxAngle); - static float ACos(AngleOf); + static float Cos(AngleOf); + static float Sin(AngleOf); + static float Tan(AngleOf); static AngleOf CosineRuleSide(float a, float b, AngleOf gamma); static AngleOf CosineRuleAngle(float a, float b, float c); From 407e7712c6fad230270198359774d56264dc4bc3 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 9 Sep 2024 15:14:06 +0200 Subject: [PATCH 085/121] Add WithDistance --- Spherical.cpp | 6 ++++++ Spherical.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/Spherical.cpp b/Spherical.cpp index 7f6c3ca..9552373 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -107,6 +107,12 @@ template <> const SphericalOf SphericalOf::zero = SphericalOf(0.0f, AngleOf(0), AngleOf(0)); +template +SphericalOf SphericalOf::WithDistance(float distance) { + SphericalOf v = SphericalOf(distance, this->horizontal, this->vertical); + return SphericalOf(); +} + template SphericalOf SphericalOf::operator-() const { SphericalOf v = diff --git a/Spherical.h b/Spherical.h index 2c4a12b..159520a 100644 --- a/Spherical.h +++ b/Spherical.h @@ -51,6 +51,8 @@ class SphericalOf { /// @brief A normalized down-oriented vector const static SphericalOf down; + SphericalOf WithDistance(float distance); + /// @brief Negate the vector /// @return The negated vector /// This will rotate the vector by 180 degrees horizontally and From a646e936ee878af6954e43a66a7b66b0b208fcf9 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 9 Sep 2024 16:02:27 +0200 Subject: [PATCH 086/121] Add ACos --- Angle.cpp | 5 +++++ Angle.h | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 166a88e..676a7e8 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -212,6 +212,11 @@ float AngleOf::Tan(AngleOf a) { return tanf(a.InRadians()); } +template +AngleOf Passer::LinearAlgebra::AngleOf::Acos(float f) { + return AngleOf::Radians(acosf(f)); +} + template <> AngleOf AngleOf::CosineRuleSide(float a, float b, diff --git a/Angle.h b/Angle.h index b65633b..c4561e5 100644 --- a/Angle.h +++ b/Angle.h @@ -59,9 +59,11 @@ class AngleOf { AngleOf toAngle, AngleOf maxAngle); - static float Cos(AngleOf); - static float Sin(AngleOf); - static float Tan(AngleOf); + static float Cos(AngleOf a); + static float Sin(AngleOf a); + static float Tan(AngleOf a); + + static AngleOf Acos(float f); static AngleOf CosineRuleSide(float a, float b, AngleOf gamma); static AngleOf CosineRuleAngle(float a, float b, float c); From 09e25a8a218690157ba46ca5f7ccd5f33eab1c07 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 12 Sep 2024 15:30:36 +0200 Subject: [PATCH 087/121] Add Asin and Atan --- Angle.cpp | 10 +++++++++- Angle.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Angle.cpp b/Angle.cpp index 676a7e8..ebc689d 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -213,9 +213,17 @@ float AngleOf::Tan(AngleOf a) { } template -AngleOf Passer::LinearAlgebra::AngleOf::Acos(float f) { +AngleOf AngleOf::Acos(float f) { return AngleOf::Radians(acosf(f)); } +template +AngleOf AngleOf::Asin(float f) { + return AngleOf::Radians(asinf(f)); +} +template +AngleOf AngleOf::Atan(float f) { + return AngleOf::Radians(atanf(f)); +} template <> AngleOf AngleOf::CosineRuleSide(float a, diff --git a/Angle.h b/Angle.h index c4561e5..7befc46 100644 --- a/Angle.h +++ b/Angle.h @@ -64,6 +64,8 @@ class AngleOf { static float Tan(AngleOf a); static AngleOf Acos(float f); + static AngleOf Asin(float f); + static AngleOf Atan(float f); static AngleOf CosineRuleSide(float a, float b, AngleOf gamma); static AngleOf CosineRuleAngle(float a, float b, float c); From 3363388a95d8fe9708b615fc2ecdc9474f4930a1 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 16 Sep 2024 15:21:16 +0200 Subject: [PATCH 088/121] Extended AngleAxis & Direction --- AngleAxis.cpp | 35 +++++++++++++++++-------------- AngleAxis.h | 28 ++++++++++++++++--------- Direction.cpp | 58 ++++++++++++++++++++++++++++++++------------------- Direction.h | 31 ++++++++++++++++----------- 4 files changed, 93 insertions(+), 59 deletions(-) diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 2ed8321..d7d7732 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -5,44 +5,47 @@ #include "AngleAxis.h" template -AngleAxis::AngleAxis() { - this->angle = AngleOf(); - this->axis = Direction(); +AngleAxisOf::AngleAxisOf() { + this->angle = 0.0F; + this->axis = DirectionOf(); } template -AngleAxis::AngleAxis(AngleOf angle, Direction axis) { +AngleAxisOf::AngleAxisOf(float angle, DirectionOf axis) { this->angle = angle; this->axis = axis; } template -AngleAxis::AngleAxis(float angle, Vector3 axis) { - this->angle = AngleOf(angle); - this->axis = Direction(axis); +AngleAxisOf::AngleAxisOf(float angle, Vector3 axis) { + this->angle = angle; + this->axis = DirectionOf(axis); } template -AngleAxis::AngleAxis(Quaternion q) { +AngleAxisOf::AngleAxisOf(Quaternion q) { float angle; Vector3 axis; q.ToAngleAxis(&angle, &axis); - this->angle = AngleOf(angle); - this->axis = Direction(axis); + this->angle = angle; + this->axis = DirectionOf(axis); } template -Quaternion AngleAxis::ToQuaternion() { +const AngleAxisOf AngleAxisOf::zero = + AngleAxisOf(0.0, DirectionOf(0, 0)); + +template +Quaternion AngleAxisOf::ToQuaternion() { Vector3 axisVector = this->axis.ToVector3(); - float angleFloat = this->angle.ToFloat(); - Quaternion q = Quaternion::AngleAxis(angleFloat, axisVector); + Quaternion q = Quaternion::AngleAxis(this->angle, axisVector); return q; } template -Direction AngleAxis::GetSwing() { +DirectionOf AngleAxisOf::GetSwing() { return this->axis; } -template class AngleAxis; -template class AngleAxis; +template class AngleAxisOf; +template class AngleAxisOf; diff --git a/AngleAxis.h b/AngleAxis.h index fbd0ec2..821e774 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -12,22 +12,30 @@ namespace Passer { namespace LinearAlgebra { -template -class AngleAxis { - public: - AngleOf angle; - Direction axis; +// Isn't this the same as SphericalOf ????????????? - AngleAxis(); - AngleAxis(AngleOf angle, Direction axis); - AngleAxis(Quaternion q); - AngleAxis(float angle, Vector3 axis); +template +class AngleAxisOf { + public: + float angle; + DirectionOf axis; + + AngleAxisOf(); + AngleAxisOf(float angle, DirectionOf axis); + AngleAxisOf(Quaternion q); + AngleAxisOf(float angle, Vector3 axis); + + const static AngleAxisOf zero; Quaternion ToQuaternion(); - Direction GetSwing(); + DirectionOf GetSwing(); }; +using AngleAxisSingle = AngleAxisOf; +using AngleAxis16 = AngleAxisOf; +using AngleAxis = AngleAxisOf; + } // namespace LinearAlgebra } // namespace Passer using namespace Passer::LinearAlgebra; diff --git a/Direction.cpp b/Direction.cpp index f17f271..dac8e50 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -10,45 +10,61 @@ #include template -Direction::Direction() { - this->horizontalAngle = AngleOf(0.0f); - this->verticalAngle = AngleOf(0.0f); +DirectionOf::DirectionOf() { + this->horizontal = AngleOf(0.0f); + this->vertical = AngleOf(0.0f); } template -Direction::Direction(AngleOf horizontal, AngleOf vertical) { - this->horizontalAngle = horizontal; - this->verticalAngle = vertical; +DirectionOf::DirectionOf(AngleOf horizontal, AngleOf vertical) { + this->horizontal = horizontal; + this->vertical = vertical; }; template -Direction::Direction(Vector3 v) { - this->horizontalAngle = +DirectionOf::DirectionOf(Vector3 v) { + this->horizontal = atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; - this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; + this->vertical = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; } template -const Direction Direction::forward = Direction(0.0f, 0.0f); +const DirectionOf DirectionOf::forward = DirectionOf(0.0f, 0.0f); template -const Direction Direction::back = Direction(180.0f, 0.0f); +const DirectionOf DirectionOf::back = DirectionOf(180.0f, 0.0f); template -const Direction Direction::up = Direction(0.0f, 90.0f); +const DirectionOf DirectionOf::up = DirectionOf(0.0f, 90.0f); template -const Direction Direction::down = Direction(0.0f, -90.0f); +const DirectionOf DirectionOf::down = DirectionOf(0.0f, -90.0f); template -const Direction Direction::left = Direction(-90.0f, 0.0f); +const DirectionOf DirectionOf::left = DirectionOf(-90.0f, 0.0f); template -const Direction Direction::right = Direction(90.0f, 0.0f); +const DirectionOf DirectionOf::right = DirectionOf(90.0f, 0.0f); template -Vector3 Direction::ToVector3() { - Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), - this->horizontalAngle.ToFloat(), 0) * +DirectionOf Passer::LinearAlgebra::DirectionOf::operator+( + const DirectionOf& v) const { + DirectionOf r = DirectionOf(this->horizontal + v.horizontal, + this->vertical + v.vertical); + return r; +} + +template +DirectionOf Passer::LinearAlgebra::DirectionOf::operator+=( + const DirectionOf& v) { + this->horizontal += v.horizontal; + this->vertical += v.vertical; + return *this; +} + +template +Vector3 DirectionOf::ToVector3() { + Vector3 v = Quaternion::Euler(-(this->vertical.InDegrees()), + this->horizontal.InDegrees(), 0) * Vector3::forward; return v; } -template class Direction; -template class Direction; -template class Direction; \ No newline at end of file +template class DirectionOf; +template class DirectionOf; +template class DirectionOf; \ No newline at end of file diff --git a/Direction.h b/Direction.h index 6978b0a..348f4d7 100644 --- a/Direction.h +++ b/Direction.h @@ -13,25 +13,32 @@ namespace LinearAlgebra { struct Vector3; template -class Direction { +class DirectionOf { public: - AngleOf horizontalAngle; - AngleOf verticalAngle; + AngleOf horizontal; + AngleOf vertical; - Direction(); - Direction(AngleOf horizontal, AngleOf vertical); - Direction(Vector3 v); + DirectionOf(); + DirectionOf(AngleOf horizontal, AngleOf vertical); + DirectionOf(Vector3 v); - const static Direction forward; - const static Direction back; - const static Direction up; - const static Direction down; - const static Direction left; - const static Direction right; + const static DirectionOf forward; + const static DirectionOf back; + const static DirectionOf up; + const static DirectionOf down; + const static DirectionOf left; + const static DirectionOf right; + + DirectionOf operator+(const DirectionOf& v) const; + DirectionOf operator+=(const DirectionOf& v); Vector3 ToVector3(); }; +using DirectionSingle = DirectionOf; +using Direction16 = DirectionOf; +using Direction = DirectionOf; + } // namespace LinearAlgebra } // namespace Passer using namespace Passer::LinearAlgebra; From 11259a92a6a802b090679bfb951d09acaa01910e Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 20 Sep 2024 12:29:47 +0200 Subject: [PATCH 089/121] Extend functionality --- Direction.cpp | 6 +++ Direction.h | 1 + Spherical.cpp | 29 +++++++++---- Spherical.h | 3 ++ SwingTwist.cpp | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ SwingTwist.h | 69 +++++++++++++++++++++++++++++++ 6 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 SwingTwist.cpp create mode 100644 SwingTwist.h diff --git a/Direction.cpp b/Direction.cpp index dac8e50..ae5b503 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -41,6 +41,12 @@ const DirectionOf DirectionOf::left = DirectionOf(-90.0f, 0.0f); template const DirectionOf DirectionOf::right = DirectionOf(90.0f, 0.0f); +template +DirectionOf Passer::LinearAlgebra::DirectionOf::operator-() const { + DirectionOf r = DirectionOf(-this->horizontal, -this->vertical); + return r; +} + template DirectionOf Passer::LinearAlgebra::DirectionOf::operator+( const DirectionOf& v) const { diff --git a/Direction.h b/Direction.h index 348f4d7..96d5bac 100644 --- a/Direction.h +++ b/Direction.h @@ -29,6 +29,7 @@ class DirectionOf { const static DirectionOf left; const static DirectionOf right; + DirectionOf operator-() const; DirectionOf operator+(const DirectionOf& v) const; DirectionOf operator+=(const DirectionOf& v); diff --git a/Spherical.cpp b/Spherical.cpp index 9552373..a6c74cc 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -70,10 +70,9 @@ SphericalOf SphericalOf::FromVector3(Vector3 v) { template Vector3 SphericalOf::ToVector3() const { - float verticalRad = - (90.0f - this->vertical.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; - float horizontalRad = - this->horizontal.ToFloat() * Passer::LinearAlgebra::Deg2Rad; + float verticalRad = (pi / 2) - this->vertical.InRadians(); + float horizontalRad = this->horizontal.InRadians(); + float cosVertical = cosf(verticalRad); float sinVertical = sinf(verticalRad); float cosHorizontal = cosf(horizontalRad); @@ -217,8 +216,12 @@ const float epsilon = 1E-05f; template float SphericalOf::DistanceBetween(const SphericalOf& v1, const SphericalOf& v2) { - SphericalOf difference = v1 - v2; - return difference.distance; + // SphericalOf difference = v1 - v2; + // return difference.distance; + Vector3 vec1 = v1.ToVector3(); + Vector3 vec2 = v2.ToVector3(); + float distance = Vector3::Distance(vec1, vec2); + return distance; } template @@ -238,7 +241,19 @@ AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, // float cdot = Float::Clamp(fraction, -1.0, 1.0); // float r = ((float)acos(cdot)) * Rad2Deg; Angle r = Vector3::Angle(v1_3, v2_3); - return AngleOf(r.ToFloat()); + return AngleOf::Degrees(r.InDegrees()); +} + +template +AngleOf Passer::LinearAlgebra::SphericalOf::SignedAngleBetween( + const SphericalOf& v1, + const SphericalOf& v2, + const SphericalOf& axis) { + Vector3 v1_vector = v1.ToVector3(); + Vector3 v2_vector = v2.ToVector3(); + Vector3 axis_vector = axis.ToVector3(); + Angle r = Vector3::SignedAngle(v1_vector, v2_vector, axis_vector); + return AngleOf::Degrees(r.InDegrees()); } template diff --git a/Spherical.h b/Spherical.h index 159520a..89480e2 100644 --- a/Spherical.h +++ b/Spherical.h @@ -109,6 +109,9 @@ class SphericalOf { const SphericalOf& v2); static AngleOf AngleBetween(const SphericalOf& v1, const SphericalOf& v2); + static AngleOf SignedAngleBetween(const SphericalOf& v1, + const SphericalOf& v2, + const SphericalOf& axis); static SphericalOf Rotate(const SphericalOf& v, AngleOf horizontalAngle, diff --git a/SwingTwist.cpp b/SwingTwist.cpp new file mode 100644 index 0000000..7899631 --- /dev/null +++ b/SwingTwist.cpp @@ -0,0 +1,109 @@ +// 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 "SwingTwist.h" + +template +SwingTwistOf::SwingTwistOf() { + // this->horizontal = AngleOf(0); + // this->vertical = AngleOf(0); + this->swing = DirectionOf(0, 0); + this->twist = AngleOf(0); +} + +template +Passer::LinearAlgebra::SwingTwistOf::SwingTwistOf(DirectionOf swing, + AngleOf twist) { + this->swing = swing; + this->twist = twist; +} + +template +SwingTwistOf::SwingTwistOf(AngleOf horizontal, + AngleOf vertical, + AngleOf twist) { + // this->horizontal = horizontal; + // this->vertical = vertical; + this->swing = DirectionOf(horizontal, vertical); + this->twist = twist; +} + +template +SwingTwistOf SwingTwistOf::Degrees(float horizontal, + float vertical, + float twist) { + DirectionOf swing = DirectionOf(AngleOf::Degrees(horizontal), + AngleOf::Degrees(vertical)); + AngleOf twistAngle = AngleOf::Degrees(twist); + SwingTwistOf orientation = SwingTwistOf(swing, twistAngle); + return orientation; +} + +template +Quaternion SwingTwistOf::ToQuaternion() { + Quaternion q = Quaternion::Euler(this->swing.vertical.ToFloat(), + this->swing.horizontal.ToFloat(), + this->twist.ToFloat()); + return q; +} + +template +SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromQuaternion( + Quaternion q) { + Vector3 angles = Quaternion::ToAngles(q); + SwingTwistOf r = + SwingTwistOf(angles.Up(), angles.Right(), angles.Forward()); + + return r; +} + +template +const SwingTwistOf SwingTwistOf::identity = SwingTwistOf(); + +template +SphericalOf SwingTwistOf::operator*(const SphericalOf& vector) const { + SphericalOf v = SphericalOf(vector.distance, + vector.horizontal + this->swing.horizontal, + vector.vertical + this->swing.vertical); + return v; +} + +template +SwingTwistOf SwingTwistOf::operator*( + const SwingTwistOf& rotation) const { + SwingTwistOf r = + SwingTwistOf(this->swing.horizontal + rotation.swing.horizontal, + this->swing.vertical + rotation.swing.vertical, + this->twist + rotation.twist); + return r; +} + +template +SwingTwistOf SwingTwistOf::operator*=(const SwingTwistOf& rotation) { + // this->swing.horizontal += rotation.swing.horizontal; + // this->swing.vertical += rotation.swing.vertical; + this->swing += rotation.swing; + this->twist += rotation.twist; + return *this; +} + +template +SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::Inverse( + SwingTwistOf rotation) { + SwingTwistOf r = SwingTwistOf(-rotation.swing, -rotation.twist); + return r; +} + +template +SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::AngleAxis( + float angle, + const SphericalOf& axis) { + Vector3 axis_vector = axis.ToVector3(); + Quaternion q = Quaternion::AngleAxis(angle, axis_vector); + SwingTwistOf r = SwingTwistOf::FromQuaternion(q); + return r; +} + +template class SwingTwistOf; +template class SwingTwistOf; \ No newline at end of file diff --git a/SwingTwist.h b/SwingTwist.h new file mode 100644 index 0000000..6258ced --- /dev/null +++ b/SwingTwist.h @@ -0,0 +1,69 @@ +// 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/. + +#ifndef SWINGTWIST_H +#define SWINGTWIST_H + +#include "RoboidControlCore/LinearAlgebra/Angle.h" +#include "RoboidControlCore/LinearAlgebra/Direction.h" +#include "RoboidControlCore/LinearAlgebra/Quaternion.h" +#include "RoboidControlCore/LinearAlgebra/Spherical.h" +// #include "RoboidControlCore/LinearAlgebra/Spherical16.h" + +namespace Passer { +namespace LinearAlgebra { + +template +class SwingTwistOf { + public: + DirectionOf swing; + AngleOf twist; + + SwingTwistOf(); + SwingTwistOf(DirectionOf swing, AngleOf twist); + SwingTwistOf(AngleOf horizontal, AngleOf vertical, AngleOf twist); + + static SwingTwistOf Degrees(float horizontal, + float vertical = 0, + float twist = 0); + Quaternion ToQuaternion(); + static SwingTwistOf FromQuaternion(Quaternion q); + + const static SwingTwistOf identity; + + /// + /// Rotate a vector using this rotation + /// + /// The vector to rotate + /// The rotated vector + SphericalOf operator*(const SphericalOf& vector) const; + /// + /// Multiply this rotation with another rotation + /// + /// The swing/twist rotation to multiply with + /// The resulting swing/twist rotation + /// The result will be this rotation rotated according to + /// the give rotation. + SwingTwistOf operator*(const SwingTwistOf& rotation) const; + SwingTwistOf operator*=(const SwingTwistOf& rotation); + + static SwingTwistOf Inverse(SwingTwistOf rotation); + + /// + /// Convert an angle/axis representation to a swingt + /// + /// The angle + /// The axis + /// The resulting quaternion + static SwingTwistOf AngleAxis(float angle, const SphericalOf& axis); +}; + +using SwingTwistSingle = SwingTwistOf; +using SwingTwist16 = SwingTwistOf; + +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#endif From 2ad6a5adb3b826d83479083039fd00cd226fcce7 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 20 Sep 2024 14:09:56 +0200 Subject: [PATCH 090/121] Fix include --- SwingTwist.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/SwingTwist.h b/SwingTwist.h index 6258ced..f1e72ca 100644 --- a/SwingTwist.h +++ b/SwingTwist.h @@ -5,11 +5,10 @@ #ifndef SWINGTWIST_H #define SWINGTWIST_H -#include "RoboidControlCore/LinearAlgebra/Angle.h" -#include "RoboidControlCore/LinearAlgebra/Direction.h" -#include "RoboidControlCore/LinearAlgebra/Quaternion.h" -#include "RoboidControlCore/LinearAlgebra/Spherical.h" -// #include "RoboidControlCore/LinearAlgebra/Spherical16.h" +#include "Angle.h" +#include "Direction.h" +#include "Quaternion.h" +#include "Spherical.h" namespace Passer { namespace LinearAlgebra { From f1c70c756ebfd58864acbbede234e62d93cc741d Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 20 Sep 2024 14:40:03 +0200 Subject: [PATCH 091/121] Fix unit tests --- Angle.cpp | 3 ++- Angle.h | 4 +++- CMakeLists.txt | 1 + Direction.cpp | 1 - SwingTwist.cpp | 2 -- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index ebc689d..7f80414 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -73,7 +73,7 @@ float Angle::SineRuleAngle(float a, float beta, float b) { //---------------------- template <> -AngleOf::AngleOf(int angle) : value((float)angle) {} +AngleOf::AngleOf(signed int angle) : value((float)angle) {} template <> AngleOf::AngleOf(float angle) : value(angle) {} @@ -83,6 +83,7 @@ AngleOf AngleOf::Degrees(float a) { AngleOf angle = AngleOf(a); return angle; } + template AngleOf AngleOf::Radians(float a) { AngleOf angle = AngleOf((a / pi) * 180); diff --git a/Angle.h b/Angle.h index 7befc46..073d97a 100644 --- a/Angle.h +++ b/Angle.h @@ -17,7 +17,9 @@ template class AngleOf { public: AngleOf() {}; - AngleOf(int f); + // These are deprecated, will move to private. + // Use Degrees/Radians instead + AngleOf(signed int f); AngleOf(float f); static AngleOf Degrees(float f); diff --git a/CMakeLists.txt b/CMakeLists.txt index cc51cb9..ef13b2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ else() "Matrix.cpp" "Axis.cpp" "AngleAxis.cpp" + "SwingTwist.cpp" "Direction.cpp" ) diff --git a/Direction.cpp b/Direction.cpp index ae5b503..0b77fe5 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -73,4 +73,3 @@ Vector3 DirectionOf::ToVector3() { template class DirectionOf; template class DirectionOf; -template class DirectionOf; \ No newline at end of file diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 7899631..0d10a16 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -6,8 +6,6 @@ template SwingTwistOf::SwingTwistOf() { - // this->horizontal = AngleOf(0); - // this->vertical = AngleOf(0); this->swing = DirectionOf(0, 0); this->twist = AngleOf(0); } From 1ea65d56b1ee69407ff0ac2f9e1f232fed7e57e5 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 20 Sep 2024 15:14:25 +0200 Subject: [PATCH 092/121] Made toQuestion const --- SwingTwist.cpp | 2 +- SwingTwist.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 0d10a16..7a7f4a8 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -39,7 +39,7 @@ SwingTwistOf SwingTwistOf::Degrees(float horizontal, } template -Quaternion SwingTwistOf::ToQuaternion() { +Quaternion SwingTwistOf::ToQuaternion() const { Quaternion q = Quaternion::Euler(this->swing.vertical.ToFloat(), this->swing.horizontal.ToFloat(), this->twist.ToFloat()); diff --git a/SwingTwist.h b/SwingTwist.h index f1e72ca..37cfede 100644 --- a/SwingTwist.h +++ b/SwingTwist.h @@ -26,7 +26,7 @@ class SwingTwistOf { static SwingTwistOf Degrees(float horizontal, float vertical = 0, float twist = 0); - Quaternion ToQuaternion(); + Quaternion ToQuaternion() const; static SwingTwistOf FromQuaternion(Quaternion q); const static SwingTwistOf identity; From 92d5ef028caaa3ed7b36d89c046569f5ac7f43aa Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 23 Sep 2024 14:20:07 +0200 Subject: [PATCH 093/121] Normalizing directions --- Angle.cpp | 2 +- Angle.h | 2 +- CMakeLists.txt | 23 +++++++++-------- Direction.cpp | 50 ++++++++++++++++++++++++------------- Direction.h | 12 +++++++-- SwingTwist.cpp | 5 ++-- test/Direction_test.cc | 56 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 116 insertions(+), 34 deletions(-) create mode 100644 test/Direction_test.cc diff --git a/Angle.cpp b/Angle.cpp index 7f80414..efad991 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -112,7 +112,7 @@ float AngleOf::InRadians() const { // AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; template -bool AngleOf::operator==(AngleOf a) { +bool AngleOf::operator==(const AngleOf a) const { return this->value == a.value; } diff --git a/Angle.h b/Angle.h index 073d97a..c9a34ad 100644 --- a/Angle.h +++ b/Angle.h @@ -33,7 +33,7 @@ class AngleOf { // static AngleOf pi; - bool operator==(AngleOf a); + bool operator==(const AngleOf a) const; bool operator>(AngleOf a); bool operator>=(AngleOf a); bool operator<(AngleOf a); diff --git a/CMakeLists.txt b/CMakeLists.txt index ef13b2f..920de6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,18 +43,21 @@ else() enable_testing() + file(GLOB_RECURSE test_srcs test/*.cc) add_executable( LinearAlgebraTest - "test/Angle_test.cc" - "test/FloatSingle_test.cc" - "test/Vector2_test.cc" - "test/Vector3_test.cc" - "test/Quaternion_test.cc" - "test/Matrix_test.cc" - "test/Polar_test.cc" - "test/Spherical_test.cc" - "test/Spherical16_test.cc" - "test/DiscreteAngle_test.cc" + ${test_srcs} + # "test/Angle_test.cc" + # "test/Direction_test.cc" + # "test/DiscreteAngle_test.cc" + # "test/FloatSingle_test.cc" + # "test/Matrix_test.cc" + # "test/Polar_test.cc" + # "test/Quaternion_test.cc" + # "test/Spherical_test.cc" + # "test/Spherical16_test.cc" + # "test/Vector2_test.cc" + # "test/Vector3_test.cc" ) target_link_libraries( LinearAlgebraTest diff --git a/Direction.cpp b/Direction.cpp index 0b77fe5..4641fd5 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -19,6 +19,7 @@ template DirectionOf::DirectionOf(AngleOf horizontal, AngleOf vertical) { this->horizontal = horizontal; this->vertical = vertical; + Normalize(); }; template @@ -26,6 +27,7 @@ DirectionOf::DirectionOf(Vector3 v) { this->horizontal = atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; this->vertical = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; + Normalize(); } template @@ -41,28 +43,33 @@ const DirectionOf DirectionOf::left = DirectionOf(-90.0f, 0.0f); template const DirectionOf DirectionOf::right = DirectionOf(90.0f, 0.0f); +template +DirectionOf Passer::LinearAlgebra::DirectionOf::Degrees(float horizontal, + float vertical) { + return DirectionOf(AngleOf::Degrees(horizontal), + AngleOf::Degrees(vertical)); +} + +template +DirectionOf Passer::LinearAlgebra::DirectionOf::Radians(float horizontal, + float vertical) { + return DirectionOf(AngleOf::Radians(horizontal), + AngleOf::Radians(vertical)); +} + +template +bool Passer::LinearAlgebra::DirectionOf::operator==( + const DirectionOf d) const { + return (this->horizontal == d.horizontal) && (this->vertical == d.vertical); +} + template DirectionOf Passer::LinearAlgebra::DirectionOf::operator-() const { - DirectionOf r = DirectionOf(-this->horizontal, -this->vertical); + DirectionOf r = DirectionOf(this->horizontal + AngleOf::Degrees(180), + -this->vertical); return r; } -template -DirectionOf Passer::LinearAlgebra::DirectionOf::operator+( - const DirectionOf& v) const { - DirectionOf r = DirectionOf(this->horizontal + v.horizontal, - this->vertical + v.vertical); - return r; -} - -template -DirectionOf Passer::LinearAlgebra::DirectionOf::operator+=( - const DirectionOf& v) { - this->horizontal += v.horizontal; - this->vertical += v.vertical; - return *this; -} - template Vector3 DirectionOf::ToVector3() { Vector3 v = Quaternion::Euler(-(this->vertical.InDegrees()), @@ -71,5 +78,14 @@ Vector3 DirectionOf::ToVector3() { return v; } +template +void DirectionOf::Normalize() { + if (this->vertical > AngleOf::Degrees(90) || + this->vertical < AngleOf::Degrees(-90)) { + this->horizontal += AngleOf::Degrees(180); + this->vertical = AngleOf::Degrees(180) - this->vertical; + } +} + template class DirectionOf; template class DirectionOf; diff --git a/Direction.h b/Direction.h index 96d5bac..54faaac 100644 --- a/Direction.h +++ b/Direction.h @@ -15,13 +15,18 @@ struct Vector3; template class DirectionOf { public: + /// @brief horizontal angle, range= (-180..180] AngleOf horizontal; + /// @brief vertical angle, range in degrees = (-90..90] AngleOf vertical; DirectionOf(); DirectionOf(AngleOf horizontal, AngleOf vertical); DirectionOf(Vector3 v); + static DirectionOf Degrees(float horizontal, float vertical); + static DirectionOf Radians(float horizontal, float vertical); + const static DirectionOf forward; const static DirectionOf back; const static DirectionOf up; @@ -29,11 +34,14 @@ class DirectionOf { const static DirectionOf left; const static DirectionOf right; + bool operator==(const DirectionOf d) const; + DirectionOf operator-() const; - DirectionOf operator+(const DirectionOf& v) const; - DirectionOf operator+=(const DirectionOf& v); Vector3 ToVector3(); + + protected: + void Normalize(); }; using DirectionSingle = DirectionOf; diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 7a7f4a8..af1b18c 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -79,9 +79,8 @@ SwingTwistOf SwingTwistOf::operator*( template SwingTwistOf SwingTwistOf::operator*=(const SwingTwistOf& rotation) { - // this->swing.horizontal += rotation.swing.horizontal; - // this->swing.vertical += rotation.swing.vertical; - this->swing += rotation.swing; + this->swing.horizontal += rotation.swing.horizontal; + this->swing.vertical += rotation.swing.vertical; this->twist += rotation.twist; return *this; } diff --git a/test/Direction_test.cc b/test/Direction_test.cc new file mode 100644 index 0000000..461140c --- /dev/null +++ b/test/Direction_test.cc @@ -0,0 +1,56 @@ +#if GTEST +#include + +#include +#include + +#include "Direction.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Direction16, Compare) { + Direction16 d = Direction16::Degrees(45, 135); + bool r; + r = (d == Direction16(Angle16::Degrees(45), Angle16::Degrees(135))); + EXPECT_TRUE(r) << "45,135 == 45, 135"; + + r = (d == + Direction16(Angle16::Degrees(45 + 360), Angle16::Degrees(135 - 360))); + EXPECT_TRUE(r) << "45+360, 135-360 == 45, 135"; +} + +TEST(Direction16, Inverse) { + Direction16 d; + Direction16 r; + + d = Direction16::Degrees(45, 135); + r = -d; + EXPECT_EQ(r, Direction16::Degrees(-135, -135)) << "-(45, 135)"; + + d = Direction16::Degrees(-45, -135); + r = -d; + EXPECT_EQ(r, Direction16::Degrees(135, 135)) << "-(-45, -135)"; + + d = Direction16::Degrees(0, 0); + r = -d; + EXPECT_EQ(r, Direction16::Degrees(180, 0)) << "-(0, 0)"; + + d = Direction16::Degrees(0, 45); + r = -d; + EXPECT_EQ(r, Direction16::Degrees(180, -45)) << "-(0, 45)"; +} + +TEST(Direction16, Equality) { + Direction16 d; + d = Direction16::Degrees(135, 45); + EXPECT_EQ(d, Direction16::Degrees(135, 45)) << "(135, 45) == (135, 45)"; + EXPECT_EQ(d, Direction16::Degrees(135 + 360, 45)) + << "(135, 45) == (135 + 360, 45) "; + EXPECT_EQ(d, Direction16::Degrees(135 - 360, 45)) + << "(135, 135) == (135 - 360, 45) "; + + d = Direction16::Degrees(0, 45 + 180); + EXPECT_EQ(d, Direction16::Degrees(180, -45)) << "(0, 45+180) == (180, -45)"; +} + +#endif \ No newline at end of file From fb5cee851f055699094650f635297a4803925cec Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 24 Sep 2024 10:29:21 +0200 Subject: [PATCH 094/121] Proper angle implementation (unit tests still fail) --- Angle.cpp | 173 +++++++++++++++++-------- Angle.h | 29 +++-- Angle16.cpp | 3 +- Angle16.h | 5 +- Angle32.h | 5 +- Angle8.cpp | 5 +- Angle8.h | 5 +- AngleAxis.cpp | 2 +- Axis.cpp | 9 +- Axis.h | 5 +- CMakeLists.txt | 3 - Direction.cpp | 27 ++-- Polar.cpp | 49 +++---- Quaternion.cpp | 2 +- Spherical.cpp | 44 ++++--- Spherical16.cpp | 257 ------------------------------------- Spherical16.h | 162 ----------------------- SwingTwist.cpp | 15 ++- Vector2.cpp | 4 +- Vector3.cpp | 14 +- test/Angle_test.cc | 234 ++++++++++++++++++--------------- test/DiscreteAngle_test.cc | 57 ++++---- test/Polar_test.cc | 83 ++++++------ test/Spherical16_test.cc | 70 +++++----- test/Spherical_test.cc | 80 ++++++------ test/Vector2_test.cc | 8 +- test/Vector3_test.cc | 28 ++-- 27 files changed, 539 insertions(+), 839 deletions(-) delete mode 100644 Spherical16.cpp delete mode 100644 Spherical16.h diff --git a/Angle.cpp b/Angle.cpp index efad991..3376e97 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -72,44 +72,105 @@ float Angle::SineRuleAngle(float a, float beta, float b) { */ //---------------------- -template <> -AngleOf::AngleOf(signed int angle) : value((float)angle) {} - -template <> -AngleOf::AngleOf(float angle) : value(angle) {} +template +AngleOf::AngleOf() : value(0) {} template -AngleOf AngleOf::Degrees(float a) { - AngleOf angle = AngleOf(a); - return angle; -} +AngleOf::AngleOf(T angle) : value(angle) {} -template -AngleOf AngleOf::Radians(float a) { - AngleOf angle = AngleOf((a / pi) * 180); - return angle; +//===== AngleSingle, AngleOf + +template <> +AngleOf AngleOf::Degrees(float angle) { + return AngleOf(angle); } template <> -float AngleOf::ToFloat() const { - return value; -} -template -float AngleOf::InDegrees() const { - return this->ToFloat(); -} -template -float AngleOf::InRadians() const { - return this->ToFloat() * Deg2Rad; +AngleOf AngleOf::Radians(float angle) { + return AngleOf(angle * Rad2Deg); } -// template <> -// AngleOf AngleOf::pi = 3.1415927410125732421875F; +template <> +float AngleOf::InDegrees() const { + return this->value; +} -// template <> -// AngleOf AngleOf::Rad2Deg = 360.0f / (pi * 2); -// template <> -// AngleOf AngleOf::Deg2Rad = (pi * 2) / 360.0f; +template <> +float AngleOf::InRadians() const { + return this->value * Deg2Rad; +} + +//===== Angle16, AngleOf + +template <> +AngleOf AngleOf::Degrees(float angle) { + if (!isfinite(angle)) { + return AngleOf(0); + } + + // map float [-180..180) to integer [-32768..32767] + signed short value = (signed short)(angle / 360.0F * 65536.0F); + return AngleOf(value); +} + +template <> +AngleOf AngleOf::Radians(float angle) { + if (!isfinite(angle)) { + return AngleOf(0); + } + + // map float [-PI..PI) to integer [-32768..32767] + signed short value = (signed short)(angle / pi * 32768.0F); + return AngleOf(value); +} + +template <> +float AngleOf::InDegrees() const { + float degrees = this->value / 65536.0f * 360.0f; + return degrees; +} + +template <> +float AngleOf::InRadians() const { + float radians = this->value / 65536.0f * (2 * pi); + return radians; +} + +//===== Angle8, AngleOf + +template <> +AngleOf AngleOf::Degrees(float angle) { + if (!isfinite(angle)) + return AngleOf(0); + + // map float [-180..180) to integer [-128..127) + signed char value = (signed char)(angle / 360.0F * 256.0F); + return AngleOf(value); +} + +template <> +AngleOf AngleOf::Radians(float angle) { + if (!isfinite(angle)) + return AngleOf(0); + + // map float [-pi..pi) to integer [-128..127) + signed char value = (signed char)(angle / pi * 128.0f); + return AngleOf(value); +} + +template <> +float AngleOf::InDegrees() const { + float degrees = this->value / 256.0f * 360.0f; + return degrees; +} + +template <> +float AngleOf::InRadians() const { + float radians = this->value / 128.0f * pi; + return radians; +} + +//===== Generic template bool AngleOf::operator==(const AngleOf a) const { @@ -136,23 +197,33 @@ bool AngleOf::operator<=(AngleOf a) { return this->value <= a.value; } -template <> -AngleOf AngleOf::operator-() const { - AngleOf angle = AngleOf(-this->value); +template +AngleOf AngleOf::operator-() const { + AngleOf angle = AngleOf(-this->value); return angle; } template <> AngleOf AngleOf::operator-(const AngleOf& a) const { - AngleOf angle = AngleOf(); - angle.value = this->value - a.value; + AngleOf angle = AngleOf(this->value - a.value); + angle = Normalize(angle); + return angle; +} +template +AngleOf AngleOf::operator-(const AngleOf& a) const { + AngleOf angle = AngleOf(this->value - a.value); return angle; } template <> AngleOf AngleOf::operator+(const AngleOf& a) const { - AngleOf angle = AngleOf(); - angle.value = this->value + a.value; + AngleOf angle = AngleOf(this->value + a.value); + angle = Normalize(angle); + return angle; +} +template +AngleOf AngleOf::operator+(const AngleOf& a) const { + AngleOf angle = AngleOf(this->value + a.value); return angle; } @@ -164,7 +235,7 @@ AngleOf AngleOf::operator+=(const AngleOf& a) { template AngleOf AngleOf::Normalize(AngleOf angle) { - float angleValue = angle.ToFloat(); + float angleValue = angle.InDegrees(); if (!isfinite(angleValue)) return angle; @@ -172,32 +243,26 @@ AngleOf AngleOf::Normalize(AngleOf angle) { angleValue += 360; while (angleValue > 180) angleValue -= 360; - return AngleOf(angleValue); + return AngleOf::Degrees(angleValue); } template <> AngleOf AngleOf::Clamp(AngleOf angle, AngleOf min, AngleOf max) { - float normalizedAngle = Normalize(angle).ToFloat(); - float r = Float::Clamp(normalizedAngle, min.ToFloat(), max.ToFloat()); + float normalizedAngle = Normalize(angle).InDegrees(); + float r = Float::Clamp(normalizedAngle, min.InDegrees(), max.InDegrees()); return r; } -// template -// Angle2 Angle2::Difference(Angle2 a, Angle2 b) { -// Angle2 r = Normalize(b - a); -// return r; -// } - template <> AngleOf AngleOf::MoveTowards(AngleOf fromAngle, AngleOf toAngle, AngleOf maxAngle) { - float d = toAngle.ToFloat() - fromAngle.ToFloat(); + float d = toAngle.InDegrees() - fromAngle.InDegrees(); int sign = signbit(d) ? -1 : 1; - d = sign * Float::Clamp(fabsf(d), 0, maxAngle.ToFloat()); - return fromAngle.ToFloat() + d; + d = sign * Float::Clamp(fabsf(d), 0, maxAngle.InDegrees()); + return fromAngle.InDegrees() + d; } template @@ -227,13 +292,10 @@ AngleOf AngleOf::Atan(float f) { } template <> -AngleOf AngleOf::CosineRuleSide(float a, - float b, - AngleOf gamma) { +AngleOf AngleOf::CosineRuleSide(float a, float b, float gamma) { float a2 = a * a; float b2 = b * b; - float d = a2 + b2 - - 2 * a * b * cosf(gamma.ToFloat() * Passer::LinearAlgebra::Deg2Rad); + float d = a2 + b2 - 2 * a * b * cosf(gamma * Passer::LinearAlgebra::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) return 0.0f; @@ -263,9 +325,10 @@ AngleOf AngleOf::SineRuleAngle(float a, AngleOf beta, float b) { float deg2rad = Deg2Rad; - float alpha = asinf(a * sinf(beta.ToFloat() * deg2rad) / b); + float alpha = asinf(a * sinf(beta.InDegrees() * deg2rad) / b); return alpha; } template class AngleOf; +template class AngleOf; template class AngleOf; diff --git a/Angle.h b/Angle.h index c9a34ad..c5e55a1 100644 --- a/Angle.h +++ b/Angle.h @@ -16,16 +16,12 @@ static float Deg2Rad = (pi * 2) / 360.0f; template class AngleOf { public: - AngleOf() {}; - // These are deprecated, will move to private. - // Use Degrees/Radians instead - AngleOf(signed int f); - AngleOf(float f); + AngleOf(); static AngleOf Degrees(float f); static AngleOf Radians(float f); - float ToFloat() const; + // float ToFloat() const; float InDegrees() const; float InRadians() const; @@ -45,18 +41,18 @@ class AngleOf { AngleOf operator+=(const AngleOf& a); friend AngleOf operator*(const AngleOf& a, float f) { - return AngleOf((float)a.ToFloat() * f); + return AngleOf::Degrees((float)a.InDegrees() * f); } friend AngleOf operator*(float f, const AngleOf& a) { - return AngleOf((float)f * a.ToFloat()); + return AngleOf::Degrees((float)f * a.InDegrees()); } static AngleOf Normalize(AngleOf a); static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); - static AngleOf Difference(AngleOf a, AngleOf b) { - AngleOf r = Normalize(b.ToFloat() - a.ToFloat()); - return r; - }; + // static AngleOf Difference(AngleOf a, AngleOf b) { + // AngleOf r = Normalize(b.InDegrees() - a.InDegrees()); + // return r; + // }; static AngleOf MoveTowards(AngleOf fromAngle, AngleOf toAngle, AngleOf maxAngle); @@ -69,18 +65,25 @@ class AngleOf { static AngleOf Asin(float f); static AngleOf Atan(float f); - static AngleOf CosineRuleSide(float a, float b, AngleOf gamma); + static AngleOf CosineRuleSide(float a, float b, float gamma); static AngleOf CosineRuleAngle(float a, float b, float c); static AngleOf SineRuleAngle(float a, AngleOf beta, float c); private: T value; + + AngleOf(T value); + // These are deprecated, will move to private. + // Use Degrees/Radians instead + // AngleOf(signed int f); + // AngleOf(float f); }; using Angle = AngleOf; using AngleSingle = AngleOf; using Angle16 = AngleOf; +using Angle8 = AngleOf; } // namespace LinearAlgebra } // namespace Passer diff --git a/Angle16.cpp b/Angle16.cpp index c7f968a..50a0d8d 100644 --- a/Angle16.cpp +++ b/Angle16.cpp @@ -1,7 +1,7 @@ // 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 #include #include "Angle.h" @@ -94,3 +94,4 @@ AngleOf AngleOf::CosineRuleAngle(float a, float gamma = acosf(d) * Passer::LinearAlgebra::Rad2Deg; return gamma; } +*/ \ No newline at end of file diff --git a/Angle16.h b/Angle16.h index c60a764..60d18de 100644 --- a/Angle16.h +++ b/Angle16.h @@ -1,5 +1,5 @@ // #include "AngleUsing.h" - +/* #include #include #include "Angle.h" @@ -37,4 +37,5 @@ typedef AngleOf Angle16; } // namespace LinearAlgebra } // namespace Passer -using namespace Passer::LinearAlgebra; \ No newline at end of file +using namespace Passer::LinearAlgebra; +*/ \ No newline at end of file diff --git a/Angle32.h b/Angle32.h index 75a6e24..4ca8434 100644 --- a/Angle32.h +++ b/Angle32.h @@ -1,5 +1,5 @@ // #include "AngleUsing.h" - +/* #include #include "Angle.h" @@ -27,4 +27,5 @@ typedef AngleOf Angle32; } // namespace LinearAlgebra } // namespace Passer -using namespace Passer::LinearAlgebra; \ No newline at end of file +using namespace Passer::LinearAlgebra; +*/ \ No newline at end of file diff --git a/Angle8.cpp b/Angle8.cpp index ff14295..a45d1a6 100644 --- a/Angle8.cpp +++ b/Angle8.cpp @@ -1,7 +1,7 @@ // 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 #include "Angle.h" @@ -56,4 +56,5 @@ AngleOf AngleOf::operator+( AngleOf angle = AngleOf(); angle.value = this->value + a.value; return angle; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/Angle8.h b/Angle8.h index c3cea33..7d4508e 100644 --- a/Angle8.h +++ b/Angle8.h @@ -1,5 +1,5 @@ // #include "AngleUsing.h" - +/* #include #include "Angle.h" @@ -31,4 +31,5 @@ typedef AngleOf Angle8; } // namespace LinearAlgebra } // namespace Passer -using namespace Passer::LinearAlgebra; \ No newline at end of file +using namespace Passer::LinearAlgebra; +*/ \ No newline at end of file diff --git a/AngleAxis.cpp b/AngleAxis.cpp index d7d7732..54a5674 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -33,7 +33,7 @@ AngleAxisOf::AngleAxisOf(Quaternion q) { template const AngleAxisOf AngleAxisOf::zero = - AngleAxisOf(0.0, DirectionOf(0, 0)); + AngleAxisOf(0.0, DirectionOf(AngleOf(), AngleOf())); template Quaternion AngleAxisOf::ToQuaternion() { diff --git a/Axis.cpp b/Axis.cpp index 02f9ebc..2403e4b 100644 --- a/Axis.cpp +++ b/Axis.cpp @@ -1,7 +1,7 @@ // 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 "Axis.h" #include "Quaternion.h" @@ -10,8 +10,8 @@ #include Axis::Axis() { - horizontalAngle = 0.0f; - verticalAngle = 0.0f; + horizontalAngle = Angle(); + verticalAngle = Angle(); } Axis::Axis(Angle horizontal, Angle vertical) { @@ -37,4 +37,5 @@ Vector3 Axis::ToVector3() { this->horizontalAngle.ToFloat(), 0) * Vector3::forward; return v; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/Axis.h b/Axis.h index 4682af7..971af2f 100644 --- a/Axis.h +++ b/Axis.h @@ -1,7 +1,7 @@ // 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/. - +/* #ifndef AXIS_H #define AXIS_H @@ -35,4 +35,5 @@ public: } // namespace Passer using namespace Passer::LinearAlgebra; -#endif \ No newline at end of file +#endif +*/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 920de6d..d57f009 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,14 +26,11 @@ else() add_library(LinearAlgebra STATIC "FloatSingle.cpp" "Angle.cpp" - "Angle8.cpp" - "Angle16.cpp" "Vector2.cpp" "Vector3.cpp" "Quaternion.cpp" "Polar.cpp" "Spherical.cpp" - "Spherical16.cpp" "Matrix.cpp" "Axis.cpp" "AngleAxis.cpp" diff --git a/Direction.cpp b/Direction.cpp index 4641fd5..8dc6bad 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -11,8 +11,8 @@ template DirectionOf::DirectionOf() { - this->horizontal = AngleOf(0.0f); - this->vertical = AngleOf(0.0f); + this->horizontal = AngleOf(); + this->vertical = AngleOf(); } template @@ -24,24 +24,29 @@ DirectionOf::DirectionOf(AngleOf horizontal, AngleOf vertical) { template DirectionOf::DirectionOf(Vector3 v) { - this->horizontal = - atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; - this->vertical = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; + this->horizontal = AngleOf::Radians(atan2f(v.Right(), v.Forward())); + this->vertical = AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); Normalize(); } template -const DirectionOf DirectionOf::forward = DirectionOf(0.0f, 0.0f); +const DirectionOf DirectionOf::forward = + DirectionOf(AngleOf(), AngleOf()); template -const DirectionOf DirectionOf::back = DirectionOf(180.0f, 0.0f); +const DirectionOf DirectionOf::back = + DirectionOf(AngleOf::Degrees(180), AngleOf()); template -const DirectionOf DirectionOf::up = DirectionOf(0.0f, 90.0f); +const DirectionOf DirectionOf::up = + DirectionOf(AngleOf(), AngleOf::Degrees(90)); template -const DirectionOf DirectionOf::down = DirectionOf(0.0f, -90.0f); +const DirectionOf DirectionOf::down = + DirectionOf(AngleOf(), AngleOf::Degrees(-90)); template -const DirectionOf DirectionOf::left = DirectionOf(-90.0f, 0.0f); +const DirectionOf DirectionOf::left = + DirectionOf(AngleOf::Degrees(-90), AngleOf()); template -const DirectionOf DirectionOf::right = DirectionOf(90.0f, 0.0f); +const DirectionOf DirectionOf::right = + DirectionOf(AngleOf::Degrees(90), AngleOf()); template DirectionOf Passer::LinearAlgebra::DirectionOf::Degrees(float horizontal, diff --git a/Polar.cpp b/Polar.cpp index cc86cca..d40bad5 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -5,19 +5,19 @@ template PolarOf::PolarOf() { this->distance = 0.0f; - this->angle = 0.0f; + this->angle = AngleOf(); } template PolarOf::PolarOf(float distance, AngleOf angle) { // distance should always be 0 or greater if (distance < 0.0f) { this->distance = -distance; - this->angle = AngleOf::Normalize(angle.ToFloat() - 180.0f); + this->angle = AngleOf::Normalize(angle - AngleOf::Degrees(180)); } else { this->distance = distance; if (this->distance == 0.0f) // angle is always 0 if distance is 0 - this->angle = 0.0f; + this->angle = AngleOf(); else this->angle = AngleOf::Normalize(angle); } @@ -26,34 +26,35 @@ PolarOf::PolarOf(float distance, AngleOf angle) { template PolarOf PolarOf::FromVector2(Vector2 v) { float distance = v.magnitude(); - AngleOf angle = Vector2::SignedAngle(Vector2::forward, v); + AngleOf angle = + AngleOf::Degrees(Vector2::SignedAngle(Vector2::forward, v)); PolarOf p = PolarOf(distance, angle); return p; } template PolarOf PolarOf::FromSpherical(SphericalOf v) { - float distance = - v.distance * cosf(v.vertical.ToFloat() * Passer::LinearAlgebra::Deg2Rad); + float distance = v.distance * cosf(v.vertical.InDegrees() * + Passer::LinearAlgebra::Deg2Rad); AngleOf angle = v.horizontal; PolarOf p = PolarOf(distance, angle); return p; } template -const PolarOf PolarOf::zero = PolarOf(0.0f, 0.0f); +const PolarOf PolarOf::zero = PolarOf(0.0f, AngleOf()); template -const PolarOf PolarOf::forward = PolarOf(1.0f, 0.0f); +const PolarOf PolarOf::forward = PolarOf(1.0f, AngleOf()); template -const PolarOf PolarOf::back = PolarOf(1.0, 180.0f); +const PolarOf PolarOf::back = PolarOf(1.0, AngleOf::Degrees(180)); template -const PolarOf PolarOf::right = PolarOf(1.0, 90.0f); +const PolarOf PolarOf::right = PolarOf(1.0, AngleOf::Degrees(90)); template -const PolarOf PolarOf::left = PolarOf(1.0, -90.0f); +const PolarOf PolarOf::left = PolarOf(1.0, AngleOf::Degrees(-90)); template bool PolarOf::operator==(const PolarOf& v) const { return (this->distance == v.distance && - this->angle.ToFloat() == v.angle.ToFloat()); + this->angle.InDegrees() == v.angle.InDegrees()); } template @@ -69,7 +70,8 @@ PolarOf PolarOf::normalized() const { template PolarOf PolarOf::operator-() const { - PolarOf v = PolarOf(this->distance, this->angle + AngleOf(180)); + PolarOf v = + PolarOf(this->distance, this->angle + AngleOf::Degrees(180)); return v; } @@ -91,8 +93,7 @@ PolarOf PolarOf::operator+(const PolarOf& v) const { if (this->distance == 0.0f) return v; - float deltaAngle = - Angle::Normalize(v.angle.ToFloat() - this->angle.ToFloat()).ToFloat(); + float deltaAngle = AngleOf::Normalize(v.angle - this->angle).InDegrees(); float rotation = deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle; @@ -102,15 +103,15 @@ PolarOf PolarOf::operator+(const PolarOf& v) const { } float newDistance = - Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat(); + Angle::CosineRuleSide(v.distance, this->distance, rotation).InDegrees(); - float angle = - Angle::CosineRuleAngle(newDistance, this->distance, v.distance).ToFloat(); + float angle = Angle::CosineRuleAngle(newDistance, this->distance, v.distance) + .InDegrees(); - float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle - : this->angle.ToFloat() + angle; - newAngle = Angle::Normalize(newAngle).ToFloat(); - PolarOf vector = PolarOf(newDistance, newAngle); + float newAngle = deltaAngle < 0.0f ? this->angle.InDegrees() - angle + : this->angle.InDegrees() + angle; + AngleOf newAngleA = AngleOf::Normalize(AngleOf::Degrees(newAngle)); + PolarOf vector = PolarOf(newDistance, newAngleA); return vector; } template @@ -133,8 +134,8 @@ PolarOf PolarOf::operator/=(float f) { template float PolarOf::Distance(const PolarOf& v1, const PolarOf& v2) { float d = Angle::CosineRuleSide(v1.distance, v2.distance, - v2.angle.ToFloat() - v1.angle.ToFloat()) - .ToFloat(); + v2.angle.InDegrees() - v1.angle.InDegrees()) + .InDegrees(); return d; } diff --git a/Quaternion.cpp b/Quaternion.cpp index 8d22db8..67a761a 100644 --- a/Quaternion.cpp +++ b/Quaternion.cpp @@ -206,7 +206,7 @@ Quaternion Quaternion::FromToRotation(Vector3 fromDirection, Vector3 axis = Vector3::Cross(fromDirection, toDirection); axis = Vector3::Normalize(axis); AngleOf angle = Vector3::SignedAngle(fromDirection, toDirection, axis); - Quaternion rotation = Quaternion::AngleAxis(angle.ToFloat(), axis); + Quaternion rotation = Quaternion::AngleAxis(angle.InDegrees(), axis); return rotation; } diff --git a/Spherical.cpp b/Spherical.cpp index a6c74cc..6143ee9 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -8,8 +8,8 @@ template SphericalOf::SphericalOf() { this->distance = 0.0f; - this->horizontal = AngleOf(0); - this->vertical = AngleOf(0); + this->horizontal = AngleOf(); + this->vertical = AngleOf(); } // template <> @@ -49,7 +49,7 @@ SphericalOf::SphericalOf(float distance, template SphericalOf SphericalOf::FromPolar(PolarOf polar) { AngleOf horizontal = polar.angle; - AngleOf vertical = AngleOf(0); + AngleOf vertical = AngleOf(); SphericalOf r = SphericalOf(polar.distance, horizontal, vertical); return r; } @@ -58,12 +58,12 @@ template SphericalOf SphericalOf::FromVector3(Vector3 v) { float distance = v.magnitude(); if (distance == 0.0f) { - return SphericalOf(distance, 0, 0); + return SphericalOf(distance, AngleOf(), AngleOf()); } else { - float verticalAngle = - (90.0f - acosf(v.Up() / distance) * Passer::LinearAlgebra::Rad2Deg); - float horizontalAngle = - atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; + AngleOf verticalAngle = + AngleOf::Radians((90.0f - acosf(v.Up() / distance))); + AngleOf horizontalAngle = + AngleOf::Radians(atan2f(v.Right(), v.Forward())); return SphericalOf(distance, horizontalAngle, verticalAngle); } } @@ -88,23 +88,29 @@ Vector3 SphericalOf::ToVector3() const { template const SphericalOf SphericalOf::zero = - SphericalOf(0.0f, AngleOf(0), AngleOf(0)); + SphericalOf(0.0f, AngleOf(), AngleOf()); template -const SphericalOf SphericalOf::forward = SphericalOf(1.0f, 0.0f, 0.0f); +const SphericalOf SphericalOf::forward = + SphericalOf(1.0f, AngleOf(), AngleOf()); template -const SphericalOf SphericalOf::back = SphericalOf(1.0f, 180.0f, 0.0f); +const SphericalOf SphericalOf::back = + SphericalOf(1.0f, AngleOf::Degrees(180), AngleOf()); template -const SphericalOf SphericalOf::right = SphericalOf(1.0f, 90.0f, 0.0f); +const SphericalOf SphericalOf::right = + SphericalOf(1.0f, AngleOf::Degrees(90), AngleOf()); template -const SphericalOf SphericalOf::left = SphericalOf(1.0f, -90.0f, 0.0f); +const SphericalOf SphericalOf::left = + SphericalOf(1.0f, AngleOf::Degrees(-90), AngleOf()); template -const SphericalOf SphericalOf::up = SphericalOf(1.0f, 0.0f, 90.0f); +const SphericalOf SphericalOf::up = + SphericalOf(1.0f, AngleOf(), AngleOf::Degrees(90)); template -const SphericalOf SphericalOf::down = SphericalOf(1.0f, 0.0f, -90.0f); +const SphericalOf SphericalOf::down = + SphericalOf(1.0f, AngleOf(), AngleOf::Degrees(-90)); template <> const SphericalOf SphericalOf::zero = - SphericalOf(0.0f, AngleOf(0), AngleOf(0)); + SphericalOf(0.0f, AngleOf(), AngleOf()); template SphericalOf SphericalOf::WithDistance(float distance) { @@ -114,9 +120,9 @@ SphericalOf SphericalOf::WithDistance(float distance) { template SphericalOf SphericalOf::operator-() const { - SphericalOf v = - SphericalOf(this->distance, this->horizontal.ToFloat() + 180.0f, - this->vertical.ToFloat() + 180.0f); + SphericalOf v = SphericalOf(this->distance, + this->horizontal + AngleOf::Degrees(180), + this->vertical + AngleOf::Degrees(180)); return v; } diff --git a/Spherical16.cpp b/Spherical16.cpp deleted file mode 100644 index d9f0c8c..0000000 --- a/Spherical16.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* -#include "Spherical16.h" - -#include "Quaternion.h" -#include "Spherical.h" - -#include - -Spherical16::Spherical16() { - this->distance = 0.0f; - this->horizontalAngle = Angle16(0); - this->verticalAngle = Angle16(0); -} - -Spherical16::Spherical16(Polar polar) { - this->distance = polar.distance; - this->horizontalAngle = Angle16(polar.angle.ToFloat()); - this->verticalAngle = Angle16(0); -} - -Spherical16::Spherical16(float distance, - Angle16 horizontalAngle, - Angle16 verticalAngle) { - if (distance < 0) { - this->distance = -distance; - this->horizontalAngle = horizontalAngle.ToFloat() - Angle16(180).ToFloat(); - this->verticalAngle = verticalAngle; - } else { - this->distance = distance; - this->horizontalAngle = horizontalAngle; - this->verticalAngle = verticalAngle; - } -} - -Spherical16::Spherical16(Vector3 v) { - this->distance = v.magnitude(); - if (distance == 0.0f) { - this->verticalAngle = 0.0f; - this->horizontalAngle = 0.0f; - } else { - this->verticalAngle = (90.0f - acosf(v.Up() / this->distance) * - Passer::LinearAlgebra::Rad2Deg); - this->horizontalAngle = - atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; - } -} - -Vector3 Passer::LinearAlgebra::Spherical16::ToVector3() { - float verticalRad = - (90.0f - this->verticalAngle.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; - float horizontalRad = - this->horizontalAngle.ToFloat() * Passer::LinearAlgebra::Deg2Rad; - float cosVertical = cosf(verticalRad); - float sinVertical = sinf(verticalRad); - float cosHorizontal = cosf(horizontalRad); - float sinHorizontal = sinf(horizontalRad); - - float x = this->distance * sinVertical * sinHorizontal; - float y = this->distance * cosVertical; - float z = this->distance * sinVertical * cosHorizontal; - - Vector3 v = Vector3(x, y, z); - return Vector3(); -} - -const Spherical16 Spherical16::zero = Spherical16(0.0f, 0.0f, 0.0f); -const Spherical16 Spherical16::forward = Spherical16(1.0f, 0.0f, 0.0f); -const Spherical16 Spherical16::back = Spherical16(1.0f, 180.0f, 0.0f); -const Spherical16 Spherical16::right = Spherical16(1.0f, 90.0f, 0.0f); -const Spherical16 Spherical16::left = Spherical16(1.0f, -90.0f, 0.0f); -const Spherical16 Spherical16::up = Spherical16(1.0f, 0.0f, 90.0f); -const Spherical16 Spherical16::down = Spherical16(1.0f, 0.0f, -90.0f); - -bool Spherical16::operator==(const Spherical16& v) const { - return (this->distance == v.distance && - this->horizontalAngle.ToFloat() == v.horizontalAngle.ToFloat() && - this->verticalAngle.ToFloat() == v.verticalAngle.ToFloat()); -} - -Spherical16 Spherical16::Normalize(const Spherical16& v) { - Spherical16 r = Spherical16(1, v.horizontalAngle, v.verticalAngle); - return r; -} -Spherical16 Spherical16::normalized() const { - Spherical16 r = Spherical16(1, this->horizontalAngle, this->verticalAngle); - return r; -} - -Spherical16 Spherical16::operator-() const { - Spherical16 v = - Spherical16(this->distance, this->horizontalAngle.ToFloat() + 180.0f, - this->verticalAngle.ToFloat() + 180.0f); - return v; -} - -Spherical16 Spherical16::operator-(const Spherical16& s2) const { - Spherical thisSpherical = - Spherical(this->distance, this->horizontalAngle.ToFloat(), - this->verticalAngle.ToFloat()); - Spherical spherical2 = Spherical(s2.distance, s2.horizontalAngle.ToFloat(), - s2.verticalAngle.ToFloat()); - - // let's do it the easy way... - Vector3 v1 = Vector3(thisSpherical); - Vector3 v2 = Vector3(spherical2); - Vector3 v = v1 - v2; - Spherical16 r = Spherical16(v); - return r; -} -Spherical16 Spherical16::operator-=(const Spherical16& v) { - *this = *this - v; - return *this; -} - -Spherical16 Spherical16::operator+(const Spherical16& s2) const { - // let's do it the easy way... - Vector3 v1 = - Vector3(Spherical(this->distance, this->horizontalAngle.ToFloat(), - this->verticalAngle.ToFloat())); - Vector3 v2 = Vector3(Spherical(s2.distance, s2.horizontalAngle.ToFloat(), - s2.verticalAngle.ToFloat())); - Vector3 v = v1 + v2; - Spherical16 r = Spherical16(v); - return r; - - // This is the hard way... - if (v2.distance <= 0) - return Spherical(this->distance, this->horizontalAngle, - this->verticalAngle); - if (this->distance <= 0) - return v2; - - float deltaHorizontalAngle = - (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); - float horizontalRotation = deltaHorizontalAngle < 0 - ? 180 + deltaHorizontalAngle - : 180 - deltaHorizontalAngle; - float deltaVerticalAngle = - Angle::Normalize(v2.verticalAngle - this->verticalAngle); - float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle - : 180 - deltaVerticalAngle; - - if (horizontalRotation == 180 && verticalRotation == 180) - // angle is too small, take this angle and add the distances - return Spherical(this->distance + v2.distance, this->horizontalAngle, - this->verticalAngle); - - Angle rotation = AngleBetween(*this, v2); - float newDistance = - Angle::CosineRuleSide(v2.distance, this->distance, rotation); - float angle = - Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); - - // Now we have to project the angle to the horizontal and vertical planes... - // The axis for the angle is the cross product of the two spherical vectors - // (which function we do not have either...) - float horizontalAngle = 0; - float verticalAngle = 0; - - float newHorizontalAngle = - deltaHorizontalAngle < 0 - ? Angle::Normalize(this->horizontalAngle - horizontalAngle) - : Angle::Normalize(this->horizontalAngle + horizontalAngle); - float newVerticalAngle = - deltaVerticalAngle < 0 - ? Angle::Normalize(this->verticalAngle - verticalAngle) - : Angle::Normalize(this->verticalAngle + verticalAngle); - - Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); - -} -Spherical16 Spherical16::operator+=(const Spherical16& v) { - *this = *this + v; - return *this; -} - -// Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { -// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); -// } -// Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) { -// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); -// } -Spherical16 Spherical16::operator*=(float f) { - this->distance *= f; - return *this; -} - -// Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { -// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); -// } -// Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) { -// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); -// } -Spherical16 Spherical16::operator/=(float f) { - this->distance /= f; - return *this; -} - -// float Spherical::GetSwing() { -// // Not sure if this is correct -// return sqrtf(horizontalAngle * horizontalAngle + -// verticalAngle * verticalAngle); -// } - -// float Spherical::Distance(const Spherical &s1, const Spherical &s2) { -// float d = 0; -// return d; -// } - -#include "AngleUsing.h" -#include "FloatSingle.h" -#include "Vector3.h" - -const float epsilon = 1E-05f; -const float Rad2Deg = 57.29578F; - -Angle Spherical16::AngleBetween(const Spherical16& v1, const Spherical16& v2) { - // float denominator = sqrtf(v1_3.sqrMagnitude() * v2_3.sqrMagnitude()); - float denominator = - v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * - // v2.distance * v2.distance); - if (denominator < epsilon) - return 0.0f; - - Vector3 v1_3 = Vector3(Spherical(v1.distance, v1.horizontalAngle.ToFloat(), - v1.verticalAngle.ToFloat())); - Vector3 v2_3 = Vector3(Spherical(v2.distance, v2.horizontalAngle.ToFloat(), - v2.verticalAngle.ToFloat())); - float dot = Vector3::Dot(v1_3, v2_3); - float fraction = dot / denominator; - if (isnan(fraction)) - return fraction; // short cut to returning NaN universally - - float cdot = Float::Clamp(fraction, -1.0, 1.0); - float r = ((float)acos(cdot)) * Rad2Deg; - return r; -} - -Spherical16 Spherical16::Rotate(const Spherical16& v, - Angle horizontalAngle, - Angle verticalAngle) { - Spherical16 r = Spherical16( - v.distance, v.horizontalAngle.ToFloat() + horizontalAngle.ToFloat(), - v.verticalAngle.ToFloat() + verticalAngle.ToFloat()); - return r; -} -Spherical16 Spherical16::RotateHorizontal(const Spherical16& v, Angle a) { - Spherical16 r = Spherical16( - v.distance, v.horizontalAngle.ToFloat() + a.ToFloat(), v.verticalAngle); - return r; -} -Spherical16 Spherical16::RotateVertical(const Spherical16& v, Angle a) { - Spherical16 r = Spherical16(v.distance, v.horizontalAngle, - v.verticalAngle.ToFloat() + a.ToFloat()); - return r; -} -*/ \ No newline at end of file diff --git a/Spherical16.h b/Spherical16.h deleted file mode 100644 index 803d179..0000000 --- a/Spherical16.h +++ /dev/null @@ -1,162 +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/. - -#ifndef SPHERICAL16_H -#define SPHERICAL16_H - -#include "Angle16.h" -#include "Polar.h" - -namespace Passer { -namespace LinearAlgebra { - -struct Vector3; - -/// @brief A spherical vector -/// @details This is a vector in 3D space using a spherical coordinate system. -/// It consists of a distance and the polar and elevation angles from a -/// reference direction. The reference direction is typically thought of -/// as a forward direction. -/// In contrast to the normal Spherical type, this version uses 16 bit integers -/// for the angles -struct Spherical16 { - public: - /// @brief The distance in meters - /// @remark The distance should never be negative - float distance; - /// @brief The angle in the horizontal plane in degrees, clockwise rotation - /// @details The angle is automatically normalized to -180 .. 180 - Angle16 horizontalAngle; - /// @brief The angle in the vertical plane in degrees. Positive is upward. - /// @details The angle is automatically normalized to -180 .. 180 - Angle16 verticalAngle; - - /// @brief Create a new spherical vector with zero degrees and distance - Spherical16(); - /// @brief Create a new spherical vector - /// @param distance The distance in meters - /// @param horizontalAngle The angle in the horizontal plane in degrees, - /// clockwise rotation - /// @param verticalAngle The angle in the vertical plan in degrees, - /// zero is forward, positive is upward - Spherical16(float distance, Angle16 horizontalAngle, Angle16 verticalAngle); - /// @brief Convert polar coordinates to spherical coordinates - /// @param polar The polar coordinate - Spherical16(Polar polar); - /// @brief Convert 3D carthesian coordinates to spherical coordinates - /// @param v Vector in 3D carthesian coordinates; - Spherical16(Vector3 v); - - Vector3 ToVector3(); - - /// @brief A spherical vector with zero degree angles and distance - const static Spherical16 zero; - /// @brief A normalized forward-oriented vector - const static Spherical16 forward; - /// @brief A normalized back-oriented vector - const static Spherical16 back; - /// @brief A normalized right-oriented vector - const static Spherical16 right; - /// @brief A normalized left-oriented vector - const static Spherical16 left; - /// @brief A normalized up-oriented vector - const static Spherical16 up; - /// @brief A normalized down-oriented vector - const static Spherical16 down; - - /// @brief Equality test to another vector - /// @param v The vector to check against - /// @return true: if it is identical to the given vector - /// @note This uses float comparison to check equality which may have strange - /// effects. Equality on floats should be avoided. - bool operator==(const Spherical16& v) const; - - /// @brief The vector length - /// @param v The vector for which you need the length - /// @return The vector length; - inline static float Magnitude(const Spherical16& v) { return v.distance; } - /// @brief The vector length - /// @return The vector length - inline float magnitude() const { return this->distance; } - - /// @brief Convert the vector to a length of 1 - /// @param v The vector to convert - /// @return The vector normalized to a length of 1 - static Spherical16 Normalize(const Spherical16& v); - /// @brief Convert the vector to a length of a - /// @return The vector normalized to a length of 1 - Spherical16 normalized() const; - - /// @brief Negate the vector - /// @return The negated vector - /// This will rotate the vector by 180 degrees horizontally and - /// vertically. Distance will stay the same. - Spherical16 operator-() const; - - /// @brief Subtract a spherical vector from this vector - /// @param v The vector to subtract - /// @return The result of the subtraction - Spherical16 operator-(const Spherical16& v) const; - Spherical16 operator-=(const Spherical16& v); - /// @brief Add a spherical vector to this vector - /// @param v The vector to add - /// @return The result of the addition - Spherical16 operator+(const Spherical16& v) const; - Spherical16 operator+=(const Spherical16& v); - - /// @brief Scale the vector uniformly up - /// @param f The scaling factor - /// @return The scaled vector - /// @remark This operation will scale the distance of the vector. The angle - /// will be unaffected. - friend Spherical16 operator*(const Spherical16& v, float f) { - return Spherical16(v.distance * f, v.horizontalAngle, v.verticalAngle); - } - friend Spherical16 operator*(float f, const Spherical16& v) { - return Spherical16( - v.distance * f, v.horizontalAngle, - v.verticalAngle); // not correct, should be f * v.distance - } - Spherical16 operator*=(float f); - /// @brief Scale the vector uniformly down - /// @param f The scaling factor - /// @return The scaled factor - /// @remark This operation will scale the distance of the vector. The angle - /// will be unaffected. - friend Spherical16 operator/(const Spherical16& v, float f) { - return Spherical16(v.distance / f, v.horizontalAngle, v.verticalAngle); - } - friend Spherical16 operator/(float f, const Spherical16& v) { - return Spherical16( - v.distance / f, v.horizontalAngle, - v.verticalAngle); // not correct, should be f / v.distance - } - Spherical16 operator/=(float f); - - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vector - /// The distance between the two vectors - // static float Distance(const Spherical16 &s1, const Spherical16 &s2); - - static Angle AngleBetween(const Spherical16& v1, const Spherical16& v2); - - static Spherical16 Rotate(const Spherical16& v, - Angle horizontalAngle, - Angle verticalAngle); - static Spherical16 RotateHorizontal(const Spherical16& v, Angle angle); - static Spherical16 RotateVertical(const Spherical16& v, Angle angle); -}; - -} // namespace LinearAlgebra -} // namespace Passer -using namespace Passer::LinearAlgebra; - -#include "Vector3.h" - -#endif -*/ \ No newline at end of file diff --git a/SwingTwist.cpp b/SwingTwist.cpp index af1b18c..57f7db5 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -6,8 +6,8 @@ template SwingTwistOf::SwingTwistOf() { - this->swing = DirectionOf(0, 0); - this->twist = AngleOf(0); + this->swing = DirectionOf(AngleOf(), AngleOf()); + this->twist = AngleOf(); } template @@ -40,9 +40,9 @@ SwingTwistOf SwingTwistOf::Degrees(float horizontal, template Quaternion SwingTwistOf::ToQuaternion() const { - Quaternion q = Quaternion::Euler(this->swing.vertical.ToFloat(), - this->swing.horizontal.ToFloat(), - this->twist.ToFloat()); + Quaternion q = Quaternion::Euler(this->swing.vertical.InDegrees(), + this->swing.horizontal.InDegrees(), + this->twist.InDegrees()); return q; } @@ -50,8 +50,9 @@ template SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromQuaternion( Quaternion q) { Vector3 angles = Quaternion::ToAngles(q); - SwingTwistOf r = - SwingTwistOf(angles.Up(), angles.Right(), angles.Forward()); + SwingTwistOf r = SwingTwistOf(AngleOf::Degrees(angles.Up()), + AngleOf::Degrees(angles.Right()), + AngleOf::Degrees(angles.Forward())); return r; } diff --git a/Vector2.cpp b/Vector2.cpp index b4b7d2d..01c72e9 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -30,7 +30,7 @@ Vector2::Vector2(Vector3 v) { y = v.Forward(); // z; } Vector2::Vector2(Polar p) { - float horizontalRad = p.angle.ToFloat() * Passer::LinearAlgebra::Deg2Rad; + float horizontalRad = p.angle.InDegrees() * Passer::LinearAlgebra::Deg2Rad; float cosHorizontal = cosf(horizontalRad); float sinHorizontal = sinf(horizontalRad); @@ -160,7 +160,7 @@ float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) { } Vector2 Vector2::Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a) { - float angleRad = a.ToFloat() * Passer::LinearAlgebra::Deg2Rad; + float angleRad = a.InDegrees() * Passer::LinearAlgebra::Deg2Rad; #if defined(AVR) float sinValue = sin(angleRad); float cosValue = cos(angleRad); // * Angle::Deg2Rad); diff --git a/Vector3.cpp b/Vector3.cpp index 4f5a95b..52ad3a0 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -32,8 +32,9 @@ Vector3::Vector3(Vector2 v) { Vector3::Vector3(Spherical s) { float verticalRad = - (90.0f - s.vertical.ToFloat()) * Passer::LinearAlgebra::Deg2Rad; - float horizontalRad = s.horizontal.ToFloat() * Passer::LinearAlgebra::Deg2Rad; + (90.0f - s.vertical.InDegrees()) * Passer::LinearAlgebra::Deg2Rad; + float horizontalRad = + s.horizontal.InDegrees() * Passer::LinearAlgebra::Deg2Rad; float cosVertical = cosf(verticalRad); float sinVertical = sinf(verticalRad); float cosHorizontal = cosf(horizontalRad); @@ -190,16 +191,17 @@ float clamp(float x, float lower, float upper) { AngleOf Vector3::Angle(const Vector3& v1, const Vector3& v2) { float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude()); if (denominator < epsilon) - return 0; + return AngleOf(); float dot = Vector3::Dot(v1, v2); float fraction = dot / denominator; if (isnan(fraction)) - return fraction; // short cut to returning NaN universally + return AngleOf::Degrees( + fraction); // short cut to returning NaN universally float cdot = clamp(fraction, -1.0, 1.0); - float r = ((float)acos(cdot)) * Rad2Deg; - return AngleOf(r); + float r = ((float)acos(cdot)); + return AngleOf::Radians(r); } AngleOf Vector3::SignedAngle(const Vector3& v1, diff --git a/test/Angle_test.cc b/test/Angle_test.cc index 694ab62..299e3c6 100644 --- a/test/Angle_test.cc +++ b/test/Angle_test.cc @@ -9,187 +9,213 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() TEST(Angle16, Compare) { - Angle16 a = Angle16(45); + Angle16 a = Angle16::Degrees(45); bool r = false; - r = a > Angle16(0); + r = a > Angle16::Degrees(0); EXPECT_TRUE(r) << "45 > 0"; - r = a > Angle16(90); + r = a > Angle16::Degrees(90); EXPECT_FALSE(r) << "45 > 90"; - r = a > Angle16(-90); + r = a > Angle16::Degrees(-90); EXPECT_TRUE(r) << "45 > -90"; } TEST(AngleSingle, Compare) { - AngleSingle a = AngleSingle(45); + AngleSingle a = AngleSingle::Degrees(45); bool r = false; - r = a > AngleSingle(0); + r = a > AngleSingle::Degrees(0); EXPECT_TRUE(r) << "45 > 0"; - r = a > AngleSingle(90); + r = a > AngleSingle::Degrees(90); EXPECT_FALSE(r) << "45 > 90"; - r = a > AngleSingle(-90); + r = a > AngleSingle::Degrees(-90); EXPECT_TRUE(r) << "45 > -90"; } TEST(Angle, Normalize) { - Angle r = 0; + Angle r = AngleSingle(); - r = Angle::Normalize(90.0f); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize 90"; + r = Angle::Normalize(AngleSingle::Degrees(90.0f)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize 90"; - r = Angle::Normalize(-90); - EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize -90"; + r = Angle::Normalize(AngleSingle::Degrees(-90)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize -90"; - r = Angle::Normalize(270); - EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize 270"; + r = Angle::Normalize(AngleSingle::Degrees(270)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270"; - r = Angle::Normalize(270 + 360); - EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize 270+360"; + r = Angle::Normalize(AngleSingle::Degrees(270 + 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270+360"; - r = Angle::Normalize(-270); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize -270"; + r = Angle::Normalize(AngleSingle::Degrees(-270)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270"; - r = Angle::Normalize(-270 - 360); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize -270-360"; + r = Angle::Normalize(AngleSingle::Degrees(-270 - 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270-360"; - r = Angle::Normalize(0); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Normalize 0"; + r = Angle::Normalize(AngleSingle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Normalize 0"; if (std::numeric_limits::is_iec559) { - r = Angle::Normalize(FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), FLOAT_INFINITY) << "Normalize INFINITY"; + r = Angle::Normalize(AngleSingle::Degrees(FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "Normalize INFINITY"; - r = Angle::Normalize(-FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), -FLOAT_INFINITY) << "Normalize INFINITY"; + r = Angle::Normalize(AngleSingle::Degrees(-FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), -FLOAT_INFINITY) << "Normalize INFINITY"; } } TEST(Angle, Clamp) { - Angle r = 0; + Angle r = AngleSingle(); - r = Angle::Clamp(1, 0, 2); - EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 0 2"; + r = Angle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), + AngleSingle::Degrees(2)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 0 2"; - r = Angle::Clamp(-1, 0, 2); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp -1 0 2"; + r = Angle::Clamp(AngleSingle::Degrees(-1), AngleSingle::Degrees(0), + AngleSingle::Degrees(2)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp -1 0 2"; - r = Angle::Clamp(3, 0, 2); - EXPECT_FLOAT_EQ(r.ToFloat(), 2) << "Clamp 3 0 2"; + r = Angle::Clamp(AngleSingle::Degrees(3), AngleSingle::Degrees(0), + AngleSingle::Degrees(2)); + EXPECT_FLOAT_EQ(r.InDegrees(), 2) << "Clamp 3 0 2"; - r = Angle::Clamp(1, 0, 0); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp 1 0 0"; + r = Angle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), + AngleSingle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 1 0 0"; - r = Angle::Clamp(0, 0, 0); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp 0 0 0"; + r = Angle::Clamp(AngleSingle::Degrees(0), AngleSingle::Degrees(0), + AngleSingle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 0 0"; - r = Angle::Clamp(0, 1, -1); - EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 0 1 -1"; + r = Angle::Clamp(AngleSingle::Degrees(0), AngleSingle::Degrees(1), + AngleSingle::Degrees(-1)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 0 1 -1"; if (std::numeric_limits::is_iec559) { - r = Angle::Clamp(1, 0, FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 0 INFINITY"; + r = Angle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), + AngleSingle::Degrees(FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 0 INFINITY"; - r = Angle::Clamp(1, -FLOAT_INFINITY, 1); - EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 -INFINITY 1"; + r = Angle::Clamp(AngleSingle::Degrees(1), + AngleSingle::Degrees(-FLOAT_INFINITY), + AngleSingle::Degrees(1)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 -INFINITY 1"; } } -TEST(Angle, Difference) { - Angle r = 0; +// TEST(Angle, Difference) { +// Angle r = 0; - r = Angle::Difference(0, 90); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference 0 90"; +// r = Angle::Difference(0, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 90"; - r = Angle::Difference(0, -90); - EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 0 -90"; +// r = Angle::Difference(0, -90); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 -90"; - r = Angle::Difference(0, 270); - EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 0 270"; +// r = Angle::Difference(0, 270); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 270"; - r = Angle::Difference(0, -270); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference 0 -270"; +// r = Angle::Difference(0, -270); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 -270"; - r = Angle::Difference(90, 0); - EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 90 0"; +// r = Angle::Difference(90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 90 0"; - r = Angle::Difference(-90, 0); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference -90 0"; +// r = Angle::Difference(-90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference -90 0"; - r = Angle::Difference(0, 0); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Difference 0 0"; +// r = Angle::Difference(0, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 0 0"; - r = Angle::Difference(90, 90); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Difference 90 90"; +// r = Angle::Difference(90, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 90 90"; - if (std::numeric_limits::is_iec559) { - r = Angle::Difference(0, INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), INFINITY) << "Difference 0 INFINITY"; +// if (std::numeric_limits::is_iec559) { +// r = Angle::Difference(0, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference 0 INFINITY"; - r = Angle::Difference(0, -INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), -INFINITY) << "Difference 0 -INFINITY"; +// r = Angle::Difference(0, -INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), -INFINITY) << "Difference 0 -INFINITY"; - r = Angle::Difference(-INFINITY, INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), INFINITY) << "Difference -INFINITY INFINITY"; - } -} +// r = Angle::Difference(-INFINITY, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference -INFINITY +// INFINITY"; +// } +// } TEST(Angle, MoveTowards) { - Angle r = 0; + Angle r = Angle(); - r = Angle::MoveTowards(0, 90, 30); - EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 90 30"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), + Angle::Degrees(30)); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 90 30"; - r = Angle::MoveTowards(0, 90, 90); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 90"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), + Angle::Degrees(90)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 90"; - r = Angle::MoveTowards(0, 90, 180); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 180"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), + Angle::Degrees(180)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 180"; - r = Angle::MoveTowards(0, 90, 270); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 270"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), + Angle::Degrees(270)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 270"; - r = Angle::MoveTowards(0, 90, -30); - EXPECT_FLOAT_EQ(r.ToFloat(), -30) << "MoveTowards 0 90 -30"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), + Angle::Degrees(-30)); + EXPECT_FLOAT_EQ(r.InDegrees(), -30) << "MoveTowards 0 90 -30"; - r = Angle::MoveTowards(0, -90, -30); - EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 -90 -30"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), + Angle::Degrees(-30)); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 -90 -30"; - r = Angle::MoveTowards(0, -90, -90); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 -90 -90"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), + Angle::Degrees(-90)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 -90 -90"; - r = Angle::MoveTowards(0, -90, -180); - EXPECT_FLOAT_EQ(r.ToFloat(), 180) << "MoveTowards 0 -90 -180"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), + Angle::Degrees(-180)); + EXPECT_FLOAT_EQ(r.InDegrees(), 180) << "MoveTowards 0 -90 -180"; - r = Angle::MoveTowards(0, -90, -270); - EXPECT_FLOAT_EQ(r.ToFloat(), 270) << "MoveTowards 0 -90 -270"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), + Angle::Degrees(-270)); + EXPECT_FLOAT_EQ(r.InDegrees(), 270) << "MoveTowards 0 -90 -270"; - r = Angle::MoveTowards(0, 90, 0); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 90 0"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), + Angle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 0"; - r = Angle::MoveTowards(0, 0, 0); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 0 0"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(0), + Angle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 0"; - r = Angle::MoveTowards(0, 0, 30); - EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 0 30"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(0), + Angle::Degrees(30)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 30"; if (std::numeric_limits::is_iec559) { - r = Angle::MoveTowards(0, 90, FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 FLOAT_INFINITY"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), + Angle::Degrees(FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 FLOAT_INFINITY"; - r = Angle::MoveTowards(0, FLOAT_INFINITY, 30); - EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 FLOAT_INFINITY 30"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(FLOAT_INFINITY), + Angle::Degrees(30)); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 FLOAT_INFINITY 30"; - r = Angle::MoveTowards(0, -90, -FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r.ToFloat(), FLOAT_INFINITY) + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), + Angle::Degrees(-FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "MoveTowards 0 -90 -FLOAT_INFINITY"; - r = Angle::MoveTowards(0, -FLOAT_INFINITY, -30); - EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; + r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-FLOAT_INFINITY), + Angle::Degrees(-30)); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; } } diff --git a/test/DiscreteAngle_test.cc b/test/DiscreteAngle_test.cc index 62e505b..373c74d 100644 --- a/test/DiscreteAngle_test.cc +++ b/test/DiscreteAngle_test.cc @@ -4,76 +4,77 @@ #include #include -#include "Angle16.h" -#include "Angle8.h" +#include "Angle.h" +// #include "Angle16.h" +// #include "Angle8.h" #define FLOAT_INFINITY std::numeric_limits::infinity() TEST(Angle8, Construct) { float angle = 0.0F; - Angle8 a = Angle8(angle); - EXPECT_FLOAT_EQ(a.ToFloat(), angle); + Angle8 a = Angle8::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); angle = -180.0F; - a = Angle8(angle); - EXPECT_FLOAT_EQ(a.ToFloat(), angle); + a = Angle8::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); } TEST(Angle8, Negate) { float angle = 0; - Angle8 a = Angle8(angle); + Angle8 a = Angle8::Degrees(angle); a = -a; - EXPECT_FLOAT_EQ(a.ToFloat(), angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); angle = 90.0F; - a = Angle8(angle); + a = Angle8::Degrees(angle); a = -a; - EXPECT_FLOAT_EQ(a.ToFloat(), -angle); + EXPECT_FLOAT_EQ(a.InDegrees(), -angle); } TEST(Angle8, Add) { - Angle8 a = Angle8(-45); - Angle8 b = Angle8(45.0F); + Angle8 a = Angle8::Degrees(-45); + Angle8 b = Angle8::Degrees(45.0F); Angle8 r = a + b; - EXPECT_FLOAT_EQ(r.ToFloat(), 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0); } TEST(Angle8, Subtract) { - Angle8 a = Angle8(0); - Angle8 b = Angle8(45.0F); + Angle8 a = Angle8::Degrees(0); + Angle8 b = Angle8::Degrees(45.0F); Angle8 r = a - b; - EXPECT_FLOAT_EQ(r.ToFloat(), -45); + EXPECT_FLOAT_EQ(r.InDegrees(), -45); } TEST(Angle16, Construct) { - Angle16 a = Angle16(0.0F); - EXPECT_FLOAT_EQ(a.ToFloat(), 0); + Angle16 a = Angle16::Degrees(0.0F); + EXPECT_FLOAT_EQ(a.InDegrees(), 0); } TEST(Angle16, Negate) { float angle = 0; - Angle16 a = Angle16(angle); + Angle16 a = Angle16::Degrees(angle); a = -a; - EXPECT_FLOAT_EQ(a.ToFloat(), angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); angle = 90.0F; - a = Angle16(angle); + a = Angle16::Degrees(angle); a = -a; - EXPECT_FLOAT_EQ(a.ToFloat(), -angle); + EXPECT_FLOAT_EQ(a.InDegrees(), -angle); } TEST(Angle16, Subtract) { - Angle16 a = Angle16(0); - Angle16 b = Angle16(45.0F); + Angle16 a = Angle16::Degrees(0); + Angle16 b = Angle16::Degrees(45.0F); Angle16 r = a - b; - EXPECT_FLOAT_EQ(r.ToFloat(), -45); + EXPECT_FLOAT_EQ(r.InDegrees(), -45); } TEST(Angle16, Add) { - Angle16 a = Angle16(-45); - Angle16 b = Angle16(45.0F); + Angle16 a = Angle16::Degrees(-45); + Angle16 b = Angle16::Degrees(45.0F); Angle16 r = a + b; - EXPECT_FLOAT_EQ(r.ToFloat(), 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0); } #endif \ No newline at end of file diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 4f28c17..9797969 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -13,90 +13,92 @@ TEST(Polar, FromVector2) { Polar p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "s.angle 0 0 1"; + EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "s.angle 0 0 1"; v = Vector2(1, 0); p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), 90.0F) << "s.angle 1 0"; + EXPECT_FLOAT_EQ(p.angle.InDegrees(), 90.0F) << "s.angle 1 0"; v = Vector2(-1, 1); p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1"; - EXPECT_NEAR(p.angle.ToFloat(), -45.0F, 1.0e-05) << "s.angle -1 1"; + EXPECT_NEAR(p.angle.InDegrees(), -45.0F, 1.0e-05) << "s.angle -1 1"; } TEST(Polar, FromSpherical) { Spherical s; Polar p; - s = Spherical(1, 0, 0); + s = Spherical(1, Angle::Degrees(0), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(1 0 0)"; + EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(1 0 0)"; - s = Spherical(1, 45, 0); + s = Spherical(1, Angle::Degrees(45), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), 45.0F) << "p.angle FromSpherical(1 45 0)"; + EXPECT_FLOAT_EQ(p.angle.InDegrees(), 45.0F) + << "p.angle FromSpherical(1 45 0)"; - s = Spherical(1, -45, 0); + s = Spherical(1, Angle::Degrees(-45), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), -45.0F) + EXPECT_FLOAT_EQ(p.angle.InDegrees(), -45.0F) << "p.angle FromSpherical(1 -45 0)"; - s = Spherical(0, 0, 0); + s = Spherical(0, Angle::Degrees(0), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 0)"; + EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 0)"; - s = Spherical(-1, 0, 0); + s = Spherical(-1, Angle::Degrees(0), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), 180.0F) << "p.angle FromSpherical(-1 0 0)"; + EXPECT_FLOAT_EQ(p.angle.InDegrees(), 180.0F) + << "p.angle FromSpherical(-1 0 0)"; - s = Spherical(0, 0, 90); + s = Spherical(0, Angle::Degrees(0), Angle::Degrees(90)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)"; - EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 90)"; + EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 90)"; } TEST(Polar, Negation) { - Polar v = Polar(2, 45); + Polar v = Polar(2, Angle::Degrees(45)); Polar r = Polar::zero; r = -v; EXPECT_FLOAT_EQ(r.distance, 2); - EXPECT_FLOAT_EQ(r.angle.ToFloat(), -135); - EXPECT_TRUE(r == Polar(2, -135)) << "Negate(2 45)"; + EXPECT_FLOAT_EQ(r.angle.InDegrees(), -135); + EXPECT_TRUE(r == Polar(2, Angle::Degrees(-135))) << "Negate(2 45)"; - v = Polar(2, -45); + v = Polar(2, Angle::Degrees(-45)); r = -v; - EXPECT_TRUE(r == Polar(2, 135)) << "Negate(2 -45)"; + EXPECT_TRUE(r == Polar(2, Angle::Degrees(135))) << "Negate(2 -45)"; - v = Polar(2, 0); + v = Polar(2, Angle::Degrees(0)); r = -v; - EXPECT_TRUE(r == Polar(2, 180)) << "Negate(2 0)"; + EXPECT_TRUE(r == Polar(2, Angle::Degrees(180))) << "Negate(2 0)"; - v = Polar(0, 0); + v = Polar(0, Angle::Degrees(0)); r = -v; EXPECT_FLOAT_EQ(r.distance, 0.0f); - EXPECT_FLOAT_EQ(r.angle.ToFloat(), 0.0f); - EXPECT_TRUE(r == Polar(0, 0)) << "Negate(0 0)"; + EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0.0f); + EXPECT_TRUE(r == Polar(0, Angle::Degrees(0))) << "Negate(0 0)"; } TEST(Polar, Subtraction) { - Polar v1 = Polar(4, 45); - Polar v2 = Polar(1, -90); + Polar v1 = Polar(4, Angle::Degrees(45)); + Polar v2 = Polar(1, Angle::Degrees(-90)); Polar r = Polar::zero; r = v1 - v2; @@ -108,8 +110,8 @@ TEST(Polar, Subtraction) { } TEST(Polar, Addition) { - Polar v1 = Polar(1, 45); - Polar v2 = Polar(1, -90); + Polar v1 = Polar(1, Angle::Degrees(45)); + Polar v2 = Polar(1, Angle::Degrees(-90)); Polar r = Polar::zero; r = v1 - v2; @@ -123,34 +125,35 @@ TEST(Polar, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; - v2 = Polar(1, -45); + v2 = Polar(1, Angle::Degrees(-45)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; - EXPECT_FLOAT_EQ(r.angle.ToFloat(), 0) << "Addition(0 0 0)"; + EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0) << "Addition(0 0 0)"; } TEST(Polar, Scale_Multiply) { - Polar v1 = Polar(4, 45); + Polar v1 = Polar(4, Angle::Degrees(45)); Polar r = Polar::zero; r = v1 * 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance * 2) << "ScaleMult(4 45, 2)"; - EXPECT_FLOAT_EQ(r.angle.ToFloat(), v1.angle.ToFloat()) + EXPECT_FLOAT_EQ(r.angle.InDegrees(), v1.angle.InDegrees()) << "ScaleMult(4 45, 2)"; } TEST(Polar, Scale_Divide) { - Polar v1 = Polar(4, 45); + Polar v1 = Polar(4, Angle::Degrees(45)); Polar r = Polar::zero; r = v1 / 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance / 2) << "ScaleDiv(4 45, 2)"; - EXPECT_FLOAT_EQ(r.angle.ToFloat(), v1.angle.ToFloat()) << "ScaleDiv(4 45, 2)"; + EXPECT_FLOAT_EQ(r.angle.InDegrees(), v1.angle.InDegrees()) + << "ScaleDiv(4 45, 2)"; } TEST(Polar, Distance) { - Polar v1 = Polar(4, 45); - Polar v2 = Polar(1, -90); + Polar v1 = Polar(4, Angle::Degrees(45)); + Polar v2 = Polar(1, Angle::Degrees(-90)); float d = 0; d = Polar::Distance(v1, v2); @@ -162,12 +165,12 @@ TEST(Polar, Distance) { } TEST(Polar, Rotate) { - Polar v = Polar(4, 45); + Polar v = Polar(4, Angle::Degrees(45)); Polar r = Polar::zero; - r = Polar::Rotate(v, 45); + r = Polar::Rotate(v, Angle::Degrees(45)); EXPECT_FLOAT_EQ(r.distance, v.distance) << "Rotate(4 45, 45)"; - EXPECT_FLOAT_EQ(r.angle.ToFloat(), 90.0f) << "Rotate(4 45, 45)"; + EXPECT_FLOAT_EQ(r.angle.InDegrees(), 90.0f) << "Rotate(4 45, 45)"; } #endif \ No newline at end of file diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index 677c383..b73499b 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -13,22 +13,22 @@ TEST(Spherical16, FromVector3) { Spherical16 s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ((float)s.horizontal.ToFloat(), 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ((float)s.vertical.ToFloat(), 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ((float)s.horizontal.InDegrees(), 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ((float)s.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; } // TEST(Spherical16, FromPolar) { @@ -36,46 +36,47 @@ TEST(Spherical16, FromVector3) { // Spherical16 s = Spherical16::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; -// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; -// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; +// EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(1 0)"; +// EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 0)"; // p = Polar(1, 45); // s = Spherical16::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; -// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; -// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; +// EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 45.0F) << "s.hor Polar(1 45)"; +// EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 45)"; // p = Polar(1, -45); // s = Spherical16::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; -// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; -// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; +// EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), -45.0F) << "s.hor Polar(1 -45)"; +// EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 -45)"; // p = Polar(0, 0); // s = Spherical16::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; -// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; -// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; +// EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(0 0)"; +// EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(0 0)"; // p = Polar(-1, 0); // s = Spherical16::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; -// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -180.0F) << "s.hor Polar(-1 0)"; -// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; +// EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), -180.0F) << "s.hor Polar(-1 0)"; +// EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(-1 0)"; // } TEST(Spherical16, Incident1) { Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); Spherical16 s = Spherical16::FromVector3(v); - Spherical16 sr = Spherical16(2.49F, 98.18f, 24.4F); + Spherical16 sr = + Spherical16(2.49F, Angle16::Degrees(98.18f), Angle16::Degrees(24.4F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-02); - EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-02); + EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-02); + EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-02); Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; @@ -87,10 +88,11 @@ TEST(Spherical16, Incident2) { Vector3 v = Vector3(1.0f, 0.0f, 1.0f); Spherical16 s = Spherical16::FromVector3(v); - Spherical16 sr = Spherical16(1.4142135623F, 45.0f, 0.0F); + Spherical16 sr = Spherical16(1.4142135623F, Angle16::Degrees(45.0f), + Angle16::Degrees(0.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); - EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -100,10 +102,10 @@ TEST(Spherical16, Incident2) { v = Vector3(0.0f, 1.0f, 1.0f); s = Spherical16::FromVector3(v); - sr = Spherical16(1.4142135623F, 0.0f, 45.0F); + sr = Spherical16(1.4142135623F, Angle16::Degrees(0), Angle16::Degrees(45)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); - EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -115,8 +117,8 @@ TEST(Spherical16, Incident2) { r = Spherical16(s.distance, s.horizontal, s.vertical).ToVector3(); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontal.ToFloat(), 45.0F, 1.0e-02); - EXPECT_NEAR(s.vertical.ToFloat(), 35.26F, 1.0e-02); + EXPECT_NEAR(s.horizontal.InDegrees(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.vertical.InDegrees(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-04); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-04); @@ -130,7 +132,7 @@ TEST(Spherical16, Incident2) { } TEST(Spherical16, Addition) { - Spherical16 v1 = Spherical16(1, 45, 0); + Spherical16 v1 = Spherical16(1, Angle16::Degrees(45), Angle16::Degrees(0)); Spherical16 v2 = Spherical16::zero; Spherical16 r = Spherical16::zero; @@ -141,17 +143,17 @@ TEST(Spherical16, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; - v2 = Spherical16(1, -45, 0); + v2 = Spherical16(1, Angle16::Degrees(-45), Angle16::Degrees(0)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; - v2 = Spherical16(1, 0, 90); + v2 = Spherical16(1, Angle16::Degrees(0), Angle16::Degrees(90)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index df338d1..7b4c50f 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -12,69 +12,70 @@ TEST(Spherical, FromVector3) { Spherical s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; } TEST(Spherical, FromPolar) { - Polar p = Polar(1, 0); + Polar p = Polar(1, Angle::Degrees(0)); Spherical s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(1 0)"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 0)"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(1 0)"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 0)"; - p = Polar(1, 45); + p = Polar(1, Angle::Degrees(45)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 45.0F) << "s.hor Polar(1 45)"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 45)"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 45.0F) << "s.hor Polar(1 45)"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 45)"; - p = Polar(1, -45); + p = Polar(1, Angle::Degrees(-45)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -45.0F) << "s.hor Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), -45.0F) << "s.hor Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 -45)"; - p = Polar(0, 0); + p = Polar(0, Angle::Degrees(0)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(0 0)"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(0 0)"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(0 0)"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(0 0)"; - p = Polar(-1, 0); + p = Polar(-1, Angle::Degrees(0)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 180.0F) << "s.hor Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 180.0F) << "s.hor Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(-1 0)"; } TEST(Spherical, Incident1) { Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); Spherical s = Spherical::FromVector3(v); - Spherical sr = Spherical(2.49F, 98.18f, 24.4F); + Spherical sr = + Spherical(2.49F, Angle::Degrees(98.18f), Angle::Degrees(24.4F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-02); - EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-02); + EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-02); + EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-02); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; @@ -86,10 +87,11 @@ TEST(Spherical, Incident2) { Vector3 v = Vector3(1.0f, 0.0f, 1.0f); Spherical s = Spherical::FromVector3(v); - Spherical sr = Spherical(1.4142135623F, 45.0f, 0.0F); + Spherical sr = + Spherical(1.4142135623F, Angle::Degrees(45.0f), Angle::Degrees(0.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); - EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -99,10 +101,10 @@ TEST(Spherical, Incident2) { v = Vector3(0.0f, 1.0f, 1.0f); s = Spherical::FromVector3(v); - sr = Spherical(1.4142135623F, 0.0f, 45.0F); + sr = Spherical(1.4142135623F, Angle::Degrees(0.0f), Angle::Degrees(45.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05); - EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05); + EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -114,8 +116,8 @@ TEST(Spherical, Incident2) { r = Vector3(s); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontal.ToFloat(), 45.0F, 1.0e-02); - EXPECT_NEAR(s.vertical.ToFloat(), 35.26F, 1.0e-02); + EXPECT_NEAR(s.horizontal.InDegrees(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.vertical.InDegrees(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); @@ -129,7 +131,7 @@ TEST(Spherical, Incident2) { } TEST(Spherical, Addition) { - Spherical v1 = Spherical(1, 45, 0); + Spherical v1 = Spherical(1, Angle::Degrees(45), Angle::Degrees(0)); Spherical v2 = Spherical::zero; Spherical r = Spherical::zero; @@ -140,17 +142,17 @@ TEST(Spherical, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; - v2 = Spherical(1, -45, 0); + v2 = Spherical(1, Angle::Degrees(-45), Angle::Degrees(0)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; - v2 = Spherical(1, 0, 90); + v2 = Spherical(1, Angle::Degrees(0), Angle::Degrees(90)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index a7561f2..3f8768e 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -462,16 +462,16 @@ TEST(Vector2, Rotate) { Vector2 v1 = Vector2(1, 2); Vector2 r = Vector2(0, 0); - r = Vector2::Rotate(v1, 0); + r = Vector2::Rotate(v1, Angle::Degrees(0)); EXPECT_FLOAT_EQ(Vector2::Distance(r, v1), 0); - r = Vector2::Rotate(v1, 180); + r = Vector2::Rotate(v1, Angle::Degrees(180)); EXPECT_NEAR(Vector2::Distance(r, Vector2(-1, -2)), 0, 1.0e-06); - r = Vector2::Rotate(v1, -90); + r = Vector2::Rotate(v1, Angle::Degrees(-90)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); - r = Vector2::Rotate(v1, 270); + r = Vector2::Rotate(v1, Angle::Degrees(270)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); } diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index 01170da..bd53b5a 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -488,29 +488,29 @@ TEST(Vector3, ProjectOnPlane) { TEST(Vector3, Angle) { Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); - AngleOf f = 0; + AngleOf f = AngleOf::Degrees(0); bool r = false; f = Vector3::Angle(v1, v2); - EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F) << "Angle(4 5 6, 1 2 3)"; + EXPECT_FLOAT_EQ(f.InDegrees(), 12.9331388F) << "Angle(4 5 6, 1 2 3)"; v2 = Vector3(-1, -2, -3); f = Vector3::Angle(v1, v2); - EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F) << "Angle(4 5 6, -1 -2 -3)"; + EXPECT_FLOAT_EQ(f.InDegrees(), 167.066864F) << "Angle(4 5 6, -1 -2 -3)"; v2 = Vector3(0, 0, 0); f = Vector3::Angle(v1, v2); - EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "Angle(4 5 6, 0 0 0)"; + EXPECT_FLOAT_EQ(f.InDegrees(), 0) << "Angle(4 5 6, 0 0 0)"; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); f = Vector3::Angle(v1, v2); - r = isnan(f.ToFloat()); + r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "Angle(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); f = Vector3::Angle(v1, v2); - r = isnan(f.ToFloat()); + r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "Angle(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -519,42 +519,42 @@ TEST(Vector3, SignedAngle) { Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v3 = Vector3(7, 8, -9); - AngleOf f = 0; + AngleOf f = AngleOf::Degrees(0); bool r = false; f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f.ToFloat(), -12.9331388F) + EXPECT_FLOAT_EQ(f.InDegrees(), -12.9331388F) << "SignedAngle(4 5 6, 1 2 3, 7 8 -9)"; v2 = Vector3(-1, -2, -3); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F) + EXPECT_FLOAT_EQ(f.InDegrees(), 167.066864F) << "SignedAngle(4 5 6, -1 -2 -3, 7 8 -9)"; v2 = Vector3(0, 0, 0); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 0 0 0, 7 8 -9 )"; + EXPECT_FLOAT_EQ(f.InDegrees(), 0) << "SignedAngle(4 5 6, 0 0 0, 7 8 -9 )"; v2 = Vector3(1, 2, 3); v3 = Vector3(-7, -8, 9); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F) + EXPECT_FLOAT_EQ(f.InDegrees(), 12.9331388F) << "SignedAngle(4 5 6, 1 2 3, -7 -8 9)"; v3 = Vector3(0, 0, 0); f = Vector3::SignedAngle(v1, v2, v3); - EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)"; + EXPECT_FLOAT_EQ(f.InDegrees(), 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)"; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); f = Vector3::SignedAngle(v1, v2, v3); - r = isnan(f.ToFloat()); + r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "SignedAngle(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); f = Vector3::SignedAngle(v1, v2, v3); - r = isnan(f.ToFloat()); + r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "SignedAngle(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } From 136e44e0001f382b6378cefa4cf17573d0b0dd98 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 24 Sep 2024 11:10:33 +0200 Subject: [PATCH 095/121] Fixed unit tests --- Spherical.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spherical.cpp b/Spherical.cpp index 6143ee9..3fc8666 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -61,7 +61,7 @@ SphericalOf SphericalOf::FromVector3(Vector3 v) { return SphericalOf(distance, AngleOf(), AngleOf()); } else { AngleOf verticalAngle = - AngleOf::Radians((90.0f - acosf(v.Up() / distance))); + AngleOf::Radians((pi / 2 - acosf(v.Up() / distance))); AngleOf horizontalAngle = AngleOf::Radians(atan2f(v.Right(), v.Forward())); return SphericalOf(distance, horizontalAngle, verticalAngle); From 0ebfce48d7517ffe5f5a39bc36af2dd8273ef510 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 24 Sep 2024 11:48:25 +0200 Subject: [PATCH 096/121] Spherical direction --- Angle16.cpp | 97 ---------------------------------------- Angle16.h | 41 ----------------- Angle32.h | 31 ------------- Angle8.cpp | 60 ------------------------- Angle8.h | 35 --------------- Polar.cpp | 4 +- Spherical.cpp | 43 ++++++++++-------- Spherical.h | 19 ++++---- SwingTwist.cpp | 6 +-- Vector3.cpp | 6 +-- test/Spherical16_test.cc | 58 +++++++++++++++--------- test/Spherical_test.cc | 72 +++++++++++++++++------------ 12 files changed, 122 insertions(+), 350 deletions(-) delete mode 100644 Angle16.cpp delete mode 100644 Angle16.h delete mode 100644 Angle32.h delete mode 100644 Angle8.cpp delete mode 100644 Angle8.h diff --git a/Angle16.cpp b/Angle16.cpp deleted file mode 100644 index 50a0d8d..0000000 --- a/Angle16.cpp +++ /dev/null @@ -1,97 +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 -#include -#include "Angle.h" - -template <> -AngleOf::AngleOf(int angle) { - signed long long_angle = (signed short)angle * 65536; - this->value = (signed short)(long_angle / 360); -} - -template <> -AngleOf::AngleOf(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); -} - -// template <> -// AngleOf::operator float() const { -// float f = ((this->value * 180) / 32768.0F); -// return f; -// } - -template <> -float AngleOf::ToFloat() const { - float f = ((this->value * 180) / 32768.0F); - return f; -} - -template <> -AngleOf AngleOf::operator-() const { - AngleOf angle = AngleOf(); - angle.value = -this->value; - return angle; -} - -template <> -AngleOf AngleOf::operator-( - const AngleOf& a) const { - AngleOf angle = AngleOf(); - angle.value = this->value - a.value; - return angle; -} - -template <> -AngleOf AngleOf::operator+( - const AngleOf& a) const { - AngleOf angle = AngleOf(); - angle.value = this->value + a.value; - return angle; -} - -// Not correct!!! just for syntactical compilation ATM -template <> -AngleOf AngleOf::CosineRuleSide( - float a, - float b, - AngleOf gamma) { - float a2 = a * a; - float b2 = b * b; - float d = a2 + b2 - - 2 * a * b * cosf(gamma.ToFloat() * Passer::LinearAlgebra::Deg2Rad); - // Catch edge cases where float inacuracies lead tot nans - if (d < 0) - return 0.0f; - - float c = sqrtf(d); - return c; -} - -// Not correct!!! just for syntactical compilation ATM -template <> -AngleOf AngleOf::CosineRuleAngle(float a, - float b, - float c) { - float a2 = a * a; - float b2 = b * b; - float c2 = c * c; - float d = (a2 + b2 - c2) / (2 * a * b); - // Catch edge cases where float inacuracies lead tot nans - if (d >= 1) - return 0.0f; - if (d <= -1) - return 180.0f; - - float gamma = acosf(d) * Passer::LinearAlgebra::Rad2Deg; - return gamma; -} -*/ \ No newline at end of file diff --git a/Angle16.h b/Angle16.h deleted file mode 100644 index 60d18de..0000000 --- a/Angle16.h +++ /dev/null @@ -1,41 +0,0 @@ -// #include "AngleUsing.h" -/* -#include -#include -#include "Angle.h" - -namespace Passer { -namespace LinearAlgebra { - -typedef AngleOf Angle16; - -// template <> -// inline static Angle16 Angle16::Degrees(short angle) { -// long long_angle = angle * 65535; -// long_angle = div(long_angle, (long)360); -// return Angle16(long_angle); //(long_angle / 360); -// } - -// template <> -// inline static Angle16 Angle16::Degrees(float angle) { -// return (angle / 360.0F * 65536.0F); -// } -// template <> Angle16::AngleOf(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); -// } - -// template <> float Angle16::ToFloat() const { -// float f = ((this->value * 180) / 32768.0F); -// return f; -// } - -} // namespace LinearAlgebra -} // namespace Passer -using namespace Passer::LinearAlgebra; -*/ \ No newline at end of file diff --git a/Angle32.h b/Angle32.h deleted file mode 100644 index 4ca8434..0000000 --- a/Angle32.h +++ /dev/null @@ -1,31 +0,0 @@ -// #include "AngleUsing.h" -/* -#include -#include "Angle.h" - -namespace Passer { -namespace LinearAlgebra { - -typedef AngleOf Angle32; - -// template <> -// Angle32::AngleOf(float angle) { -// if (!isfinite(angle)) { -// value = 0; -// return; -// } - -// // map float [-180..180) to integer [-2147483648..2147483647] -// this->value = (signed long)((angle / 360.0F) * 4294967295.0F); -// } - -// template <> -// float Angle32::ToFloat() const { -// float f = ((this->value * 180) / 2147483648.0F); -// return f; -// } - -} // namespace LinearAlgebra -} // namespace Passer -using namespace Passer::LinearAlgebra; -*/ \ No newline at end of file diff --git a/Angle8.cpp b/Angle8.cpp deleted file mode 100644 index a45d1a6..0000000 --- a/Angle8.cpp +++ /dev/null @@ -1,60 +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 -#include "Angle.h" - -template <> -AngleOf::AngleOf(int angle) { - signed short short_angle = (signed char)angle * 256; - this->value = (signed char)(short_angle / 360); -} - -template <> -AngleOf::AngleOf(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); -} - -// template <> -// AngleOf::operator float() const { -// float f = (this->value * 180) / 128.0F; -// return f; -// } - -template <> -float AngleOf::ToFloat() const { - float f = (this->value * 180) / 128.0F; - return f; -} - -template <> -AngleOf AngleOf::operator-() const { - AngleOf angle = AngleOf(); - angle.value = -this->value; - return angle; -} - -template <> -AngleOf AngleOf::operator-( - const AngleOf& a) const { - AngleOf angle = AngleOf(); - angle.value = this->value - a.value; - return angle; -} - -template <> -AngleOf AngleOf::operator+( - const AngleOf& a) const { - AngleOf angle = AngleOf(); - angle.value = this->value + a.value; - return angle; -} -*/ \ No newline at end of file diff --git a/Angle8.h b/Angle8.h deleted file mode 100644 index 7d4508e..0000000 --- a/Angle8.h +++ /dev/null @@ -1,35 +0,0 @@ -// #include "AngleUsing.h" -/* -#include -#include "Angle.h" - -namespace Passer { -namespace LinearAlgebra { - -typedef AngleOf Angle8; - -// template <> -// inline static Angle8 Angle8::Degrees(float angle) { -// return (angle / 360.0F * 256.0F); -// } - -// template <> Angle8::AngleOf(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); -// } - -// template <> float Angle8::ToFloat() const { -// float f = (this->value * 180) / 128.0F; -// return f; -// } - -} // namespace LinearAlgebra -} // namespace Passer -using namespace Passer::LinearAlgebra; -*/ \ No newline at end of file diff --git a/Polar.cpp b/Polar.cpp index d40bad5..2ca014b 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -33,9 +33,9 @@ PolarOf PolarOf::FromVector2(Vector2 v) { } template PolarOf PolarOf::FromSpherical(SphericalOf v) { - float distance = v.distance * cosf(v.vertical.InDegrees() * + float distance = v.distance * cosf(v.direction.vertical.InDegrees() * Passer::LinearAlgebra::Deg2Rad); - AngleOf angle = v.horizontal; + AngleOf angle = v.direction.horizontal; PolarOf p = PolarOf(distance, angle); return p; } diff --git a/Spherical.cpp b/Spherical.cpp index 3fc8666..a88f704 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -8,8 +8,9 @@ template SphericalOf::SphericalOf() { this->distance = 0.0f; - this->horizontal = AngleOf(); - this->vertical = AngleOf(); + this->direction = DirectionOf(); + // this->horizontal = AngleOf(); + // this->vertical = AngleOf(); } // template <> @@ -24,8 +25,15 @@ SphericalOf::SphericalOf(float distance, AngleOf horizontal, AngleOf vertical) { this->distance = distance; - this->horizontal = horizontal; - this->vertical = vertical; + this->direction = DirectionOf(horizontal, vertical); + // this->horizontal = horizontal; + // this->vertical = vertical; +} + +template +SphericalOf::SphericalOf(float distance, DirectionOf direction) { + this->distance = distance; + this->direction = direction; } // template <> @@ -70,8 +78,8 @@ SphericalOf SphericalOf::FromVector3(Vector3 v) { template Vector3 SphericalOf::ToVector3() const { - float verticalRad = (pi / 2) - this->vertical.InRadians(); - float horizontalRad = this->horizontal.InRadians(); + float verticalRad = (pi / 2) - this->direction.vertical.InRadians(); + float horizontalRad = this->direction.horizontal.InRadians(); float cosVertical = cosf(verticalRad); float sinVertical = sinf(verticalRad); @@ -108,21 +116,17 @@ template const SphericalOf SphericalOf::down = SphericalOf(1.0f, AngleOf(), AngleOf::Degrees(-90)); -template <> -const SphericalOf SphericalOf::zero = - SphericalOf(0.0f, AngleOf(), AngleOf()); - template SphericalOf SphericalOf::WithDistance(float distance) { - SphericalOf v = SphericalOf(distance, this->horizontal, this->vertical); + SphericalOf v = SphericalOf(distance, this->direction); return SphericalOf(); } template SphericalOf SphericalOf::operator-() const { - SphericalOf v = SphericalOf(this->distance, - this->horizontal + AngleOf::Degrees(180), - this->vertical + AngleOf::Degrees(180)); + SphericalOf v = SphericalOf( + this->distance, this->direction.horizontal + AngleOf::Degrees(180), + this->direction.vertical + AngleOf::Degrees(180)); return v; } @@ -266,20 +270,23 @@ template SphericalOf SphericalOf::Rotate(const SphericalOf& v, AngleOf horizontalAngle, AngleOf verticalAngle) { - SphericalOf r = SphericalOf(v.distance, v.horizontal + horizontalAngle, - v.vertical + verticalAngle); + SphericalOf r = + SphericalOf(v.distance, v.direction.horizontal + horizontalAngle, + v.direction.vertical + verticalAngle); return r; } template SphericalOf SphericalOf::RotateHorizontal(const SphericalOf& v, AngleOf a) { - SphericalOf r = SphericalOf(v.distance, v.horizontal + a, v.vertical); + SphericalOf r = + SphericalOf(v.distance, v.direction.horizontal + a, v.direction.vertical); return r; } template SphericalOf SphericalOf::RotateVertical(const SphericalOf& v, AngleOf a) { - SphericalOf r = SphericalOf(v.distance, v.horizontal, v.vertical + a); + SphericalOf r = + SphericalOf(v.distance, v.direction.horizontal, v.direction.vertical + a); return r; } diff --git a/Spherical.h b/Spherical.h index 89480e2..8d71891 100644 --- a/Spherical.h +++ b/Spherical.h @@ -5,8 +5,7 @@ #ifndef SPHERICAL_H #define SPHERICAL_H -#include "Angle.h" -// #include "Polar.h" +#include "Direction.h" namespace Passer { namespace LinearAlgebra { @@ -23,13 +22,15 @@ class SphericalOf { float distance; /// @brief The angle in the horizontal plane in degrees, clockwise rotation /// @details The angle is automatically normalized to -180 .. 180 - AngleOf horizontal; + // AngleOf horizontal; /// @brief The angle in the vertical plane in degrees. Positive is upward. /// @details The angle is automatically normalized to -180 .. 180 - AngleOf vertical; + // AngleOf vertical; + DirectionOf direction; SphericalOf(); SphericalOf(float distance, AngleOf horizontal, AngleOf vertical); + SphericalOf(float distance, DirectionOf direction); static SphericalOf FromPolar(PolarOf v); @@ -76,11 +77,10 @@ class SphericalOf { /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. friend SphericalOf operator*(const SphericalOf& v, float f) { - return SphericalOf(v.distance * f, v.horizontal, v.vertical); + return SphericalOf(v.distance * f, v.direction); } friend SphericalOf operator*(float f, const SphericalOf& v) { - return SphericalOf(v.distance * f, v.horizontal, - v.vertical); // not correct, should be f * v.distance + return SphericalOf(f * v.distance, v.direction); } SphericalOf operator*=(float f); /// @brief Scale the vector uniformly down @@ -89,11 +89,10 @@ class SphericalOf { /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. friend SphericalOf operator/(const SphericalOf& v, float f) { - return SphericalOf(v.distance / f, v.horizontal, v.vertical); + return SphericalOf(v.distance / f, v.direction); } friend SphericalOf operator/(float f, const SphericalOf& v) { - return SphericalOf(v.distance / f, v.horizontal, - v.vertical); // not correct, should be f / v.distance + return SphericalOf(f / v.distance, v.direction); } SphericalOf operator/=(float f); diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 57f7db5..88390a2 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -62,9 +62,9 @@ const SwingTwistOf SwingTwistOf::identity = SwingTwistOf(); template SphericalOf SwingTwistOf::operator*(const SphericalOf& vector) const { - SphericalOf v = SphericalOf(vector.distance, - vector.horizontal + this->swing.horizontal, - vector.vertical + this->swing.vertical); + SphericalOf v = SphericalOf( + vector.distance, vector.direction.horizontal + this->swing.horizontal, + vector.direction.vertical + this->swing.vertical); return v; } diff --git a/Vector3.cpp b/Vector3.cpp index 52ad3a0..958fdaf 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -31,10 +31,10 @@ Vector3::Vector3(Vector2 v) { } Vector3::Vector3(Spherical s) { - float verticalRad = - (90.0f - s.vertical.InDegrees()) * Passer::LinearAlgebra::Deg2Rad; + float verticalRad = (90.0f - s.direction.vertical.InDegrees()) * + Passer::LinearAlgebra::Deg2Rad; float horizontalRad = - s.horizontal.InDegrees() * Passer::LinearAlgebra::Deg2Rad; + s.direction.horizontal.InDegrees() * Passer::LinearAlgebra::Deg2Rad; float cosVertical = cosf(verticalRad); float sinVertical = sinf(verticalRad); float cosHorizontal = cosf(horizontalRad); diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index b73499b..4f445c9 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -13,22 +13,24 @@ TEST(Spherical16, FromVector3) { Spherical16 s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ((float)s.horizontal.InDegrees(), 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ((float)s.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ((float)s.direction.horizontal.InDegrees(), 0.0F) + << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ((float)s.direction.vertical.InDegrees(), 0.0F) + << "s.vert 0 0 1"; v = Vector3(0, 1, 0); s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); s = Spherical16::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; } // TEST(Spherical16, FromPolar) { @@ -75,10 +77,14 @@ TEST(Spherical16, Incident1) { Spherical16 sr = Spherical16(2.49F, Angle16::Degrees(98.18f), Angle16::Degrees(24.4F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-02); - EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-02); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), + sr.direction.horizontal.InDegrees(), 1.0e-02); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-02); - Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); + Vector3 r = + Spherical16(sr.distance, sr.direction.horizontal, sr.direction.vertical) + .ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0"; EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0"; @@ -91,10 +97,14 @@ TEST(Spherical16, Incident2) { Spherical16 sr = Spherical16(1.4142135623F, Angle16::Degrees(45.0f), Angle16::Degrees(0.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); - EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), + sr.direction.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-05); - Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); + Vector3 r = + Spherical16(sr.distance, sr.direction.horizontal, sr.direction.vertical) + .ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); @@ -104,21 +114,25 @@ TEST(Spherical16, Incident2) { sr = Spherical16(1.4142135623F, Angle16::Degrees(0), Angle16::Degrees(45)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); - EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), + sr.direction.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-05); - r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3(); + r = Spherical16(sr.distance, sr.direction.horizontal, sr.direction.vertical) + .ToVector3(); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); s = Spherical16::FromVector3(v); - r = Spherical16(s.distance, s.horizontal, s.vertical).ToVector3(); + r = Spherical16(s.distance, s.direction.horizontal, s.direction.vertical) + .ToVector3(); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontal.InDegrees(), 45.0F, 1.0e-02); - EXPECT_NEAR(s.vertical.InDegrees(), 35.26F, 1.0e-02); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.direction.vertical.InDegrees(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-04); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-04); @@ -146,14 +160,14 @@ TEST(Spherical16, Addition) { v2 = Spherical16(1, Angle16::Degrees(-45), Angle16::Degrees(0)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; v2 = Spherical16(1, Angle16::Degrees(0), Angle16::Degrees(90)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 7b4c50f..cd8dcad 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -12,22 +12,22 @@ TEST(Spherical, FromVector3) { Spherical s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 0 1"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; } TEST(Spherical, FromPolar) { @@ -35,36 +35,46 @@ TEST(Spherical, FromPolar) { Spherical s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(1 0)"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 0)"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) + << "s.hor Polar(1 0)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(1 0)"; p = Polar(1, Angle::Degrees(45)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 45.0F) << "s.hor Polar(1 45)"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 45)"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 45.0F) + << "s.hor Polar(1 45)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(1 45)"; p = Polar(1, Angle::Degrees(-45)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), -45.0F) << "s.hor Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), -45.0F) + << "s.hor Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(1 -45)"; p = Polar(0, Angle::Degrees(0)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(0 0)"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(0 0)"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) + << "s.hor Polar(0 0)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(0 0)"; p = Polar(-1, Angle::Degrees(0)); s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 180.0F) << "s.hor Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 180.0F) + << "s.hor Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(-1 0)"; } TEST(Spherical, Incident1) { @@ -74,8 +84,10 @@ TEST(Spherical, Incident1) { Spherical sr = Spherical(2.49F, Angle::Degrees(98.18f), Angle::Degrees(24.4F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-02); - EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-02); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), + sr.direction.horizontal.InDegrees(), 1.0e-02); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-02); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; @@ -90,8 +102,10 @@ TEST(Spherical, Incident2) { Spherical sr = Spherical(1.4142135623F, Angle::Degrees(45.0f), Angle::Degrees(0.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); - EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), + sr.direction.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-05); Vector3 r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -103,8 +117,10 @@ TEST(Spherical, Incident2) { sr = Spherical(1.4142135623F, Angle::Degrees(0.0f), Angle::Degrees(45.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.horizontal.InDegrees(), sr.horizontal.InDegrees(), 1.0e-05); - EXPECT_NEAR(s.vertical.InDegrees(), sr.vertical.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), + sr.direction.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-05); r = Vector3(sr); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); @@ -116,8 +132,8 @@ TEST(Spherical, Incident2) { r = Vector3(s); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.horizontal.InDegrees(), 45.0F, 1.0e-02); - EXPECT_NEAR(s.vertical.InDegrees(), 35.26F, 1.0e-02); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), 45.0F, 1.0e-02); + EXPECT_NEAR(s.direction.vertical.InDegrees(), 35.26F, 1.0e-02); EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); @@ -145,14 +161,14 @@ TEST(Spherical, Addition) { v2 = Spherical(1, Angle::Degrees(-45), Angle::Degrees(0)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; + EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; v2 = Spherical(1, Angle::Degrees(0), Angle::Degrees(90)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.vertical.InDegrees(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; + EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 45) << "Addition(1 0 90)"; } #endif \ No newline at end of file From 9eca3189918ecfbaae462427619c263f636b6d9d Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 24 Sep 2024 12:25:37 +0200 Subject: [PATCH 097/121] Fixed inverse --- SwingTwist.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 88390a2..a82097c 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -89,7 +89,8 @@ SwingTwistOf SwingTwistOf::operator*=(const SwingTwistOf& rotation) { template SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::Inverse( SwingTwistOf rotation) { - SwingTwistOf r = SwingTwistOf(-rotation.swing, -rotation.twist); + SwingTwistOf r = SwingTwistOf( + -rotation.swing.horizontal, -rotation.swing.vertical, -rotation.twist); return r; } From 95a6fb3a4b5eca70dee33381611e5df9d28fdcee Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 25 Sep 2024 09:39:44 +0200 Subject: [PATCH 098/121] Improved Angle quality --- Angle.cpp | 192 +++++++++++++++------------- Angle.h | 10 +- FloatSingle.cpp | 12 +- Polar.cpp | 9 +- test/Angle16_test.cc | 239 +++++++++++++++++++++++++++++++++++ test/Angle8_test.cc | 239 +++++++++++++++++++++++++++++++++++ test/AngleSingle_test.cc | 247 +++++++++++++++++++++++++++++++++++++ test/Angle_test.cc | 4 +- test/DiscreteAngle_test.cc | 4 +- test/FloatSingle_test.cc | 38 +++--- test/Polar_test.cc | 2 +- test/Spherical_test.cc | 2 +- 12 files changed, 872 insertions(+), 126 deletions(-) create mode 100644 test/Angle16_test.cc create mode 100644 test/Angle8_test.cc create mode 100644 test/AngleSingle_test.cc diff --git a/Angle.cpp b/Angle.cpp index 3376e97..5b71d0d 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -19,57 +19,8 @@ float Angle::Normalize(float angle) { angle -= 360; return angle; } - -float Angle::Clamp(float angle, float min, float max) { - float normalizedAngle = Normalize(angle); - float r = Float::Clamp(normalizedAngle, min, max); - return r; -} - -float Angle::Difference(float a, float b) { - float r = Normalize(b - a); - return r; -} - -float Angle::MoveTowards(float fromAngle, float toAngle, float maxAngle) { - float d = toAngle - fromAngle; - float sign = signbit(d) ? -1 : 1; - d = sign * Float::Clamp(fabs(d), 0, maxAngle); - return fromAngle + d; -} - -float Angle::CosineRuleSide(float a, float b, float gamma) { - float a2 = a * a; - float b2 = b * b; - float d = a2 + b2 - 2 * a * b * cos(gamma * Angle::Deg2Rad); - // Catch edge cases where float inacuracies lead tot nans - if (d < 0) - return 0; - - float c = sqrtf(d); - return c; -} - -float Angle::CosineRuleAngle(float a, float b, float c) { - float a2 = a * a; - float b2 = b * b; - float c2 = c * c; - float d = (a2 + b2 - c2) / (2 * a * b); - // Catch edge cases where float inacuracies lead tot nans - if (d >= 1) - return 0; - if (d <= -1) - return 180; - - float gamma = acos(d) * Angle::Rad2Deg; - return gamma; -} - -float Angle::SineRuleAngle(float a, float beta, float b) { - float alpha = asin(a * sin(beta * Angle::Deg2Rad) / b); - return alpha; -} */ + //---------------------- template @@ -82,11 +33,25 @@ AngleOf::AngleOf(T angle) : value(angle) {} template <> AngleOf AngleOf::Degrees(float angle) { + if (isfinite(angle)) { + while (angle < -180) + angle += 360; + while (angle >= 180) + angle -= 360; + } + return AngleOf(angle); } template <> AngleOf AngleOf::Radians(float angle) { + if (isfinite(angle)) { + while (angle <= -pi) + angle += 2 * pi; + while (angle > pi) + angle -= 2 * pi; + } + return AngleOf(angle * Rad2Deg); } @@ -104,10 +69,6 @@ float AngleOf::InRadians() const { template <> AngleOf AngleOf::Degrees(float angle) { - if (!isfinite(angle)) { - return AngleOf(0); - } - // map float [-180..180) to integer [-32768..32767] signed short value = (signed short)(angle / 360.0F * 65536.0F); return AngleOf(value); @@ -140,9 +101,6 @@ float AngleOf::InRadians() const { template <> AngleOf AngleOf::Degrees(float angle) { - if (!isfinite(angle)) - return AngleOf(0); - // map float [-180..180) to integer [-128..127) signed char value = (signed char)(angle / 360.0F * 256.0F); return AngleOf(value); @@ -197,6 +155,23 @@ bool AngleOf::operator<=(AngleOf a) { return this->value <= a.value; } +template +signed int Passer::LinearAlgebra::AngleOf::Sign(AngleOf a) { + if (a.value < 0) + return -1; + if (a.value > 0) + return 1; + return 0; +} + +template +AngleOf Passer::LinearAlgebra::AngleOf::Abs(AngleOf a) { + if (Sign(a) < 0) + return -a; + else + return a; +} + template AngleOf AngleOf::operator-() const { AngleOf angle = AngleOf(-this->value); @@ -246,23 +221,24 @@ AngleOf AngleOf::Normalize(AngleOf angle) { return AngleOf::Degrees(angleValue); } -template <> -AngleOf AngleOf::Clamp(AngleOf angle, - AngleOf min, - AngleOf max) { - float normalizedAngle = Normalize(angle).InDegrees(); - float r = Float::Clamp(normalizedAngle, min.InDegrees(), max.InDegrees()); - return r; +template +AngleOf AngleOf::Clamp(AngleOf angle, AngleOf min, AngleOf max) { + float r = Float::Clamp(angle.InDegrees(), min.InDegrees(), max.InDegrees()); + return AngleOf::Degrees(r); } -template <> -AngleOf AngleOf::MoveTowards(AngleOf fromAngle, - AngleOf toAngle, - AngleOf maxAngle) { - float d = toAngle.InDegrees() - fromAngle.InDegrees(); - int sign = signbit(d) ? -1 : 1; - d = sign * Float::Clamp(fabsf(d), 0, maxAngle.InDegrees()); - return fromAngle.InDegrees() + d; +template +AngleOf AngleOf::MoveTowards(AngleOf fromAngle, + AngleOf toAngle, + float maxDegrees) { + maxDegrees = fmaxf(0, maxDegrees); // filter out negative distances + AngleOf d = toAngle - fromAngle; + float dDegrees = Abs(d).InDegrees(); + d = AngleOf::Degrees(Float::Clamp(dDegrees, 0, maxDegrees)); + if (Sign(d) < 0) + d = -d; + + return fromAngle + d; } template @@ -291,41 +267,83 @@ AngleOf AngleOf::Atan(float f) { return AngleOf::Radians(atanf(f)); } -template <> -AngleOf AngleOf::CosineRuleSide(float a, float b, float gamma) { +// template <> +// float AngleOf::CosineRuleSide(float a, float b, AngleOf gamma) +// { +// float a2 = a * a; +// float b2 = b * b; +// float d = +// a2 + b2 - +// 2 * a * b * Cos(gamma); // cosf(gamma * +// Passer::LinearAlgebra::Deg2Rad); +// // Catch edge cases where float inacuracies lead tot nans +// if (d < 0) +// return 0.0f; + +// float c = sqrtf(d); +// return c; +// } + +template +float AngleOf::CosineRuleSide(float a, float b, AngleOf gamma) { float a2 = a * a; float b2 = b * b; - float d = a2 + b2 - 2 * a * b * cosf(gamma * Passer::LinearAlgebra::Deg2Rad); + float d = + a2 + b2 - + 2 * a * b * Cos(gamma); // cosf(gamma * Passer::LinearAlgebra::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) - return 0.0f; + return 0; float c = sqrtf(d); return c; } -template <> -AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { +// template <> +// AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { +// float a2 = a * a; +// float b2 = b * b; +// float c2 = c * c; +// float d = (a2 + b2 - c2) / (2 * a * b); +// // Catch edge cases where float inacuracies lead tot nans +// if (d >= 1) +// return 0.0f; +// if (d <= -1) +// return 180.0f; + +// float gamma = acosf(d) * Rad2Deg; +// return gamma; +// } +template +AngleOf AngleOf::CosineRuleAngle(float a, float b, float c) { float a2 = a * a; float b2 = b * b; float c2 = c * c; float d = (a2 + b2 - c2) / (2 * a * b); // Catch edge cases where float inacuracies lead tot nans if (d >= 1) - return 0.0f; + return AngleOf(); if (d <= -1) - return 180.0f; + return AngleOf::Degrees(180); - float gamma = acosf(d) * Rad2Deg; + // float gamma = acosf(d) * Rad2Deg; + AngleOf gamma = Acos(d); return gamma; } -template <> -AngleOf AngleOf::SineRuleAngle(float a, - AngleOf beta, - float b) { - float deg2rad = Deg2Rad; - float alpha = asinf(a * sinf(beta.InDegrees() * deg2rad) / b); +// template <> +// AngleOf AngleOf::SineRuleAngle(float a, +// AngleOf beta, +// float b) { +// float deg2rad = Deg2Rad; +// float alpha = asinf(a * sinf(beta.InDegrees() * deg2rad) / b); +// return alpha; +// } +template +AngleOf AngleOf::SineRuleAngle(float a, AngleOf beta, float b) { + // float deg2rad = Deg2Rad; + // float alpha = asinf(a * sinf(beta.InDegrees() * deg2rad) / b); + AngleOf alpha = Asin(a * Sin(beta) / b); return alpha; } diff --git a/Angle.h b/Angle.h index c5e55a1..59ba151 100644 --- a/Angle.h +++ b/Angle.h @@ -21,20 +21,20 @@ class AngleOf { static AngleOf Degrees(float f); static AngleOf Radians(float f); - // float ToFloat() const; float InDegrees() const; float InRadians() const; inline T GetBinary() const { return this->value; } - // static AngleOf pi; - bool operator==(const AngleOf a) const; bool operator>(AngleOf a); bool operator>=(AngleOf a); bool operator<(AngleOf a); bool operator<=(AngleOf a); + static signed int Sign(AngleOf a); + static AngleOf Abs(AngleOf a); + AngleOf operator-() const; AngleOf operator-(const AngleOf& a) const; AngleOf operator+(const AngleOf& a) const; @@ -55,7 +55,7 @@ class AngleOf { // }; static AngleOf MoveTowards(AngleOf fromAngle, AngleOf toAngle, - AngleOf maxAngle); + float maxAngle); static float Cos(AngleOf a); static float Sin(AngleOf a); @@ -65,7 +65,7 @@ class AngleOf { static AngleOf Asin(float f); static AngleOf Atan(float f); - static AngleOf CosineRuleSide(float a, float b, float gamma); + static float CosineRuleSide(float a, float b, AngleOf gamma); static AngleOf CosineRuleAngle(float a, float b, float c); static AngleOf SineRuleAngle(float a, AngleOf beta, float c); diff --git a/FloatSingle.cpp b/FloatSingle.cpp index fb6f301..a8c5db1 100644 --- a/FloatSingle.cpp +++ b/FloatSingle.cpp @@ -2,16 +2,16 @@ // 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 #include "FloatSingle.h" +#include const float Float::epsilon = 1e-05f; const float Float::sqrEpsilon = 1e-10f; float Float::Clamp(float f, float min, float max) { - if (f < min) - return min; - if (f > max) - return max; - return f; + if (f < min) + return min; + if (f > max) + return max; + return f; } \ No newline at end of file diff --git a/Polar.cpp b/Polar.cpp index 2ca014b..35d1576 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -102,8 +102,8 @@ PolarOf PolarOf::operator+(const PolarOf& v) const { return PolarOf(this->distance + v.distance, this->angle); } - float newDistance = - Angle::CosineRuleSide(v.distance, this->distance, rotation).InDegrees(); + float newDistance = AngleOf::CosineRuleSide(v.distance, this->distance, + AngleOf::Degrees(rotation)); float angle = Angle::CosineRuleAngle(newDistance, this->distance, v.distance) .InDegrees(); @@ -133,9 +133,8 @@ PolarOf PolarOf::operator/=(float f) { template float PolarOf::Distance(const PolarOf& v1, const PolarOf& v2) { - float d = Angle::CosineRuleSide(v1.distance, v2.distance, - v2.angle.InDegrees() - v1.angle.InDegrees()) - .InDegrees(); + float d = + AngleOf::CosineRuleSide(v1.distance, v2.distance, v2.angle - v1.angle); return d; } diff --git a/test/Angle16_test.cc b/test/Angle16_test.cc new file mode 100644 index 0000000..3f0fec2 --- /dev/null +++ b/test/Angle16_test.cc @@ -0,0 +1,239 @@ +#if GTEST +#include + +#include +#include + +#include "Angle.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Angle16, Construct) { + float angle = 0.0F; + Angle16 a = Angle16::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = -180.0F; + a = Angle16::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = 270.0F; + a = Angle16::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), -90); +} + +TEST(Angle16, Negate) { + float angle = 0; + Angle16 a = Angle16::Degrees(angle); + a = -a; + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = 90.0F; + a = Angle16::Degrees(angle); + a = -a; + EXPECT_FLOAT_EQ(a.InDegrees(), -angle); +} + +TEST(Angle16, Subtract) { + Angle16 a = Angle16::Degrees(0); + Angle16 b = Angle16::Degrees(45.0F); + Angle16 r = a - b; + EXPECT_FLOAT_EQ(r.InDegrees(), -45); +} + +TEST(Angle16, Add) { + Angle16 a = Angle16::Degrees(-45); + Angle16 b = Angle16::Degrees(45.0F); + Angle16 r = a + b; + EXPECT_FLOAT_EQ(r.InDegrees(), 0); +} + +TEST(Angle16, Compare) { + Angle16 a = Angle16::Degrees(45); + bool r = false; + + r = a > Angle16::Degrees(0); + EXPECT_TRUE(r) << "45 > 0"; + + r = a > Angle16::Degrees(90); + EXPECT_FALSE(r) << "45 > 90"; + + r = a > Angle16::Degrees(-90); + EXPECT_TRUE(r) << "45 > -90"; +} + +TEST(Angle16, Normalize) { + Angle16 r = Angle16(); + + r = Angle16::Normalize(Angle16::Degrees(90.0f)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize 90"; + + r = Angle16::Normalize(Angle16::Degrees(-90)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize -90"; + + r = Angle16::Normalize(Angle16::Degrees(270)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270"; + + r = Angle16::Normalize(Angle16::Degrees(270 + 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270+360"; + + r = Angle16::Normalize(Angle16::Degrees(-270)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270"; + + r = Angle16::Normalize(Angle16::Degrees(-270 - 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270-360"; + + r = Angle16::Normalize(Angle16::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Normalize 0"; + + if (false) { // std::numeric_limits::is_iec559) { + // Infinites are not supported + r = Angle16::Normalize(Angle16::Degrees(FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "Normalize INFINITY"; + + r = Angle16::Normalize(Angle16::Degrees(-FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), -FLOAT_INFINITY) << "Normalize INFINITY"; + } +} + +TEST(Angle16, Clamp) { + Angle16 r = Angle16(); + + // Clamp(1, 0, 2) will fail because Angle16 does not have enough resolution + // for this. Instead we use Clamp(10, 0, 20) etc. + r = Angle16::Clamp(Angle16::Degrees(10), Angle16::Degrees(0), + Angle16::Degrees(20)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-2) << "Clamp 10 0 20"; + + r = Angle16::Clamp(Angle16::Degrees(-10), Angle16::Degrees(0), + Angle16::Degrees(20)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp -10 0 20"; + + r = Angle16::Clamp(Angle16::Degrees(30), Angle16::Degrees(0), + Angle16::Degrees(20)); + EXPECT_NEAR(r.InDegrees(), 20, 1.0e-2) << "Clamp 30 0 20"; + + r = Angle16::Clamp(Angle16::Degrees(10), Angle16::Degrees(0), + Angle16::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 10 0 0"; + + r = Angle16::Clamp(Angle16::Degrees(0), Angle16::Degrees(0), + Angle16::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 0 0"; + + r = Angle16::Clamp(Angle16::Degrees(0), Angle16::Degrees(10), + Angle16::Degrees(-10)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-2) << "Clamp 0 10 -10"; + + if (false) { // std::numeric_limits::is_iec559) { + // Infinites are not supported + r = Angle16::Clamp(Angle16::Degrees(10), Angle16::Degrees(0), + Angle16::Degrees(FLOAT_INFINITY)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-2) << "Clamp 1 0 INFINITY"; + + r = Angle16::Clamp(Angle16::Degrees(10), Angle16::Degrees(-FLOAT_INFINITY), + Angle16::Degrees(10)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-2) << "Clamp 1 -INFINITY 1"; + } +} + +// TEST(Angle16, Difference) { +// Angle16 r = 0; + +// r = Angle16::Difference(0, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 90"; + +// r = Angle16::Difference(0, -90); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 -90"; + +// r = Angle16::Difference(0, 270); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 270"; + +// r = Angle16::Difference(0, -270); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 -270"; + +// r = Angle16::Difference(90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 90 0"; + +// r = Angle16::Difference(-90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference -90 0"; + +// r = Angle16::Difference(0, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 0 0"; + +// r = Angle16::Difference(90, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 90 90"; + +// if (std::numeric_limits::is_iec559) { +// r = Angle16::Difference(0, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference 0 INFINITY"; + +// r = Angle16::Difference(0, -INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), -INFINITY) << "Difference 0 -INFINITY"; + +// r = Angle16::Difference(-INFINITY, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference -INFINITY +// INFINITY"; +// } +// } + +TEST(Angle16, MoveTowards) { + Angle16 r = Angle16(); + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(90), 30); + EXPECT_NEAR(r.InDegrees(), 30, 1.0e-2) << "MoveTowards 0 90 30"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(90), 90); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 90"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(-90), 180); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 -90 -180"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(90), 270); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 270"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(90), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 -30"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(-90), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -30"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(-90), -90); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -90"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(-90), -180); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -180"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(-90), -270); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -270"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(90), 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 0"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(0), 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 0"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(0), 30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 30"; + + if (false) { // std::numeric_limits::is_iec559) { + // infinites are not supported + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(90), + FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 FLOAT_INFINITY"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), + Angle16::Degrees(FLOAT_INFINITY), 30); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 FLOAT_INFINITY 30"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(-90), + -FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) + << "MoveTowards 0 -90 -FLOAT_INFINITY"; + + r = Angle16::MoveTowards(Angle16::Degrees(0), + Angle16::Degrees(-FLOAT_INFINITY), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; + } +} +#endif \ No newline at end of file diff --git a/test/Angle8_test.cc b/test/Angle8_test.cc new file mode 100644 index 0000000..bb220c5 --- /dev/null +++ b/test/Angle8_test.cc @@ -0,0 +1,239 @@ +#if GTEST +#include + +#include +#include + +#include "Angle.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Angle8, Construct) { + float angle = 0.0F; + Angle8 a = Angle8::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = -180.0F; + a = Angle8::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = 270.0F; + a = Angle8::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), -90); +} + +TEST(Angle8, Negate) { + float angle = 0; + Angle8 a = Angle8::Degrees(angle); + a = -a; + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = 90.0F; + a = Angle8::Degrees(angle); + a = -a; + EXPECT_FLOAT_EQ(a.InDegrees(), -angle); +} + +TEST(Angle8, Add) { + Angle8 a = Angle8::Degrees(-45); + Angle8 b = Angle8::Degrees(45.0F); + Angle8 r = a + b; + EXPECT_FLOAT_EQ(r.InDegrees(), 0); +} + +TEST(Angle8, Subtract) { + Angle8 a = Angle8::Degrees(0); + Angle8 b = Angle8::Degrees(45.0F); + Angle8 r = a - b; + EXPECT_FLOAT_EQ(r.InDegrees(), -45); +} + +TEST(Angle8, Compare) { + Angle8 a = Angle8::Degrees(45); + bool r = false; + + r = a > Angle8::Degrees(0); + EXPECT_TRUE(r) << "45 > 0"; + + r = a > Angle8::Degrees(90); + EXPECT_FALSE(r) << "45 > 90"; + + r = a > Angle8::Degrees(-90); + EXPECT_TRUE(r) << "45 > -90"; +} + +TEST(Angle8, Normalize) { + Angle8 r = Angle8(); + + r = Angle8::Normalize(Angle8::Degrees(90.0f)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize 90"; + + r = Angle8::Normalize(Angle8::Degrees(-90)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize -90"; + + r = Angle8::Normalize(Angle8::Degrees(270)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270"; + + r = Angle8::Normalize(Angle8::Degrees(270 + 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270+360"; + + r = Angle8::Normalize(Angle8::Degrees(-270)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270"; + + r = Angle8::Normalize(Angle8::Degrees(-270 - 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270-360"; + + r = Angle8::Normalize(Angle8::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Normalize 0"; + + if (false) { // std::numeric_limits::is_iec559) { + // Infinites are not supported + r = Angle8::Normalize(Angle8::Degrees(FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "Normalize INFINITY"; + + r = Angle8::Normalize(Angle8::Degrees(-FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), -FLOAT_INFINITY) << "Normalize INFINITY"; + } +} + +TEST(Angle8, Clamp) { + Angle8 r = Angle8(); + + // Clamp(1, 0, 2) will fail because Angle8 does not have enough resolution for + // this. Instead we use Clamp(10, 0, 20) etc. + r = Angle8::Clamp(Angle8::Degrees(10), Angle8::Degrees(0), + Angle8::Degrees(20)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-0) << "Clamp 10 0 20"; + + r = Angle8::Clamp(Angle8::Degrees(-10), Angle8::Degrees(0), + Angle8::Degrees(20)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp -10 0 20"; + + r = Angle8::Clamp(Angle8::Degrees(30), Angle8::Degrees(0), + Angle8::Degrees(20)); + EXPECT_NEAR(r.InDegrees(), 20, 1.0e-0) << "Clamp 30 0 20"; + + r = Angle8::Clamp(Angle8::Degrees(10), Angle8::Degrees(0), + Angle8::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 10 0 0"; + + r = Angle8::Clamp(Angle8::Degrees(0), Angle8::Degrees(0), Angle8::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 0 0"; + + r = Angle8::Clamp(Angle8::Degrees(0), Angle8::Degrees(10), + Angle8::Degrees(-10)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-0) << "Clamp 0 10 -10"; + + if (false) { // std::numeric_limits::is_iec559) { + // Infinites are not supported + r = Angle8::Clamp(Angle8::Degrees(10), Angle8::Degrees(0), + Angle8::Degrees(FLOAT_INFINITY)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-0) << "Clamp 1 0 INFINITY"; + + r = Angle8::Clamp(Angle8::Degrees(10), Angle8::Degrees(-FLOAT_INFINITY), + Angle8::Degrees(10)); + EXPECT_NEAR(r.InDegrees(), 10, 1.0e-0) << "Clamp 1 -INFINITY 1"; + } +} + +// TEST(Angle8, Difference) { +// Angle8 r = 0; + +// r = Angle8::Difference(0, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 90"; + +// r = Angle8::Difference(0, -90); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 -90"; + +// r = Angle8::Difference(0, 270); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 270"; + +// r = Angle8::Difference(0, -270); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 -270"; + +// r = Angle8::Difference(90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 90 0"; + +// r = Angle8::Difference(-90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference -90 0"; + +// r = Angle8::Difference(0, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 0 0"; + +// r = Angle8::Difference(90, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 90 90"; + +// if (std::numeric_limits::is_iec559) { +// r = Angle8::Difference(0, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference 0 INFINITY"; + +// r = Angle8::Difference(0, -INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), -INFINITY) << "Difference 0 -INFINITY"; + +// r = Angle8::Difference(-INFINITY, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference -INFINITY +// INFINITY"; +// } +// } + +TEST(Angle8, MoveTowards) { + Angle8 r = Angle8(); + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(90), 30); + EXPECT_NEAR(r.InDegrees(), 30, 1.0e-0) << "MoveTowards 0 90 30"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(90), 90); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 90"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(-90), 180); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 -90 -180"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(90), 270); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 270"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(90), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 -30"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(-90), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -30"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(-90), -90); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -90"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(-90), -180); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -180"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(-90), -270); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -270"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(90), 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 0"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(0), 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 0"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(0), 30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 30"; + + if (false) { // std::numeric_limits::is_iec559) { + // infinites are not supported + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(90), + FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 FLOAT_INFINITY"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(FLOAT_INFINITY), + 30); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 FLOAT_INFINITY 30"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(-90), + -FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) + << "MoveTowards 0 -90 -FLOAT_INFINITY"; + + r = Angle8::MoveTowards(Angle8::Degrees(0), + Angle8::Degrees(-FLOAT_INFINITY), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; + } +} + +#endif \ No newline at end of file diff --git a/test/AngleSingle_test.cc b/test/AngleSingle_test.cc new file mode 100644 index 0000000..cc0774e --- /dev/null +++ b/test/AngleSingle_test.cc @@ -0,0 +1,247 @@ +#if GTEST +#include + +#include +#include + +#include "Angle.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(AngleSingle, Construct) { + float angle = 0.0F; + AngleSingle a = AngleSingle::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = -180.0F; + a = AngleSingle::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = 270.0F; + a = AngleSingle::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), -90); +} + +TEST(AngleSingle, Negate) { + float angle = 0; + AngleSingle a = AngleSingle::Degrees(angle); + a = -a; + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = 90.0F; + a = AngleSingle::Degrees(angle); + a = -a; + EXPECT_FLOAT_EQ(a.InDegrees(), -angle); +} + +TEST(AngleSingle, Add) { + AngleSingle a = AngleSingle::Degrees(-45); + AngleSingle b = AngleSingle::Degrees(45.0F); + AngleSingle r = a + b; + EXPECT_FLOAT_EQ(r.InDegrees(), 0); +} + +TEST(AngleSingle, Subtract) { + AngleSingle a = AngleSingle::Degrees(0); + AngleSingle b = AngleSingle::Degrees(45.0F); + AngleSingle r = a - b; + EXPECT_FLOAT_EQ(r.InDegrees(), -45); +} + +TEST(AngleSingle, Compare) { + AngleSingle a = AngleSingle::Degrees(45); + bool r = false; + + r = a > AngleSingle::Degrees(0); + EXPECT_TRUE(r) << "45 > 0"; + + r = a > AngleSingle::Degrees(90); + EXPECT_FALSE(r) << "45 > 90"; + + r = a > AngleSingle::Degrees(-90); + EXPECT_TRUE(r) << "45 > -90"; +} + +TEST(AngleSingle, Normalize) { + Angle r = AngleSingle(); + + r = AngleSingle::Normalize(AngleSingle::Degrees(90.0f)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize 90"; + + r = AngleSingle::Normalize(AngleSingle::Degrees(-90)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize -90"; + + r = AngleSingle::Normalize(AngleSingle::Degrees(270)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270"; + + r = AngleSingle::Normalize(AngleSingle::Degrees(270 + 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270+360"; + + r = AngleSingle::Normalize(AngleSingle::Degrees(-270)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270"; + + r = AngleSingle::Normalize(AngleSingle::Degrees(-270 - 360)); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270-360"; + + r = AngleSingle::Normalize(AngleSingle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Normalize 0"; + + if (std::numeric_limits::is_iec559) { + r = AngleSingle::Normalize(AngleSingle::Degrees(FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "Normalize INFINITY"; + + r = AngleSingle::Normalize(AngleSingle::Degrees(-FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), -FLOAT_INFINITY) << "Normalize INFINITY"; + } +} + +TEST(AngleSingle, Clamp) { + Angle r = AngleSingle(); + + r = AngleSingle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), + AngleSingle::Degrees(2)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 0 2"; + + r = AngleSingle::Clamp(AngleSingle::Degrees(-1), AngleSingle::Degrees(0), + AngleSingle::Degrees(2)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp -1 0 2"; + + r = AngleSingle::Clamp(AngleSingle::Degrees(3), AngleSingle::Degrees(0), + AngleSingle::Degrees(2)); + EXPECT_FLOAT_EQ(r.InDegrees(), 2) << "Clamp 3 0 2"; + + r = AngleSingle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), + AngleSingle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 1 0 0"; + + r = AngleSingle::Clamp(AngleSingle::Degrees(0), AngleSingle::Degrees(0), + AngleSingle::Degrees(0)); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 0 0"; + + r = AngleSingle::Clamp(AngleSingle::Degrees(0), AngleSingle::Degrees(1), + AngleSingle::Degrees(-1)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 0 1 -1"; + + if (std::numeric_limits::is_iec559) { + r = AngleSingle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), + AngleSingle::Degrees(FLOAT_INFINITY)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 0 INFINITY"; + + r = AngleSingle::Clamp(AngleSingle::Degrees(1), + AngleSingle::Degrees(-FLOAT_INFINITY), + AngleSingle::Degrees(1)); + EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 -INFINITY 1"; + } +} + +// TEST(AngleSingle, Difference) { +// Angle r = 0; + +// r = AngleSingle::Difference(0, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 90"; + +// r = AngleSingle::Difference(0, -90); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 -90"; + +// r = AngleSingle::Difference(0, 270); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 270"; + +// r = AngleSingle::Difference(0, -270); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 -270"; + +// r = AngleSingle::Difference(90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 90 0"; + +// r = AngleSingle::Difference(-90, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference -90 0"; + +// r = AngleSingle::Difference(0, 0); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 0 0"; + +// r = AngleSingle::Difference(90, 90); +// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 90 90"; + +// if (std::numeric_limits::is_iec559) { +// r = AngleSingle::Difference(0, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference 0 INFINITY"; + +// r = AngleSingle::Difference(0, -INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), -INFINITY) << "Difference 0 -INFINITY"; + +// r = AngleSingle::Difference(-INFINITY, INFINITY); +// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference -INFINITY +// INFINITY"; +// } +// } + +TEST(AngleSingle, MoveTowards) { + AngleSingle r = AngleSingle(); + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(90), 30); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 90 30"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(90), 90); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 90"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(90), 180); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 180"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(90), 270); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 270"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(90), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 -30"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(-90), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -30"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(-90), -90); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -90"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(-90), -180); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -180"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(-90), -270); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -270"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(90), 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 0"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), AngleSingle::Degrees(0), + 0); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 0"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), AngleSingle::Degrees(0), + 30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 30"; + + if (std::numeric_limits::is_iec559) { + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(90), FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 FLOAT_INFINITY"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(FLOAT_INFINITY), 30); + EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 FLOAT_INFINITY 30"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(-90), -FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -90 -FLOAT_INFINITY"; + + r = AngleSingle::MoveTowards(AngleSingle::Degrees(0), + AngleSingle::Degrees(-FLOAT_INFINITY), -30); + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 -FLOAT_INFINITY -30"; + } +} + +#endif \ No newline at end of file diff --git a/test/Angle_test.cc b/test/Angle_test.cc index 299e3c6..6cda76e 100644 --- a/test/Angle_test.cc +++ b/test/Angle_test.cc @@ -1,3 +1,4 @@ +/* #if GTEST #include @@ -219,4 +220,5 @@ TEST(Angle, MoveTowards) { } } -#endif \ No newline at end of file +#endif +*/ \ No newline at end of file diff --git a/test/DiscreteAngle_test.cc b/test/DiscreteAngle_test.cc index 373c74d..91a7cc8 100644 --- a/test/DiscreteAngle_test.cc +++ b/test/DiscreteAngle_test.cc @@ -1,3 +1,4 @@ +/* #if GTEST #include @@ -77,4 +78,5 @@ TEST(Angle16, Add) { EXPECT_FLOAT_EQ(r.InDegrees(), 0); } -#endif \ No newline at end of file +#endif +*/ \ No newline at end of file diff --git a/test/FloatSingle_test.cc b/test/FloatSingle_test.cc index 3083985..58e9d6d 100644 --- a/test/FloatSingle_test.cc +++ b/test/FloatSingle_test.cc @@ -9,33 +9,33 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() TEST(FloatC, Clamp) { - float r = 0; + float r = 0; - r = Float::Clamp(1, 0, 2); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 2"; + r = Float::Clamp(1, 0, 2); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 2"; - r = Float::Clamp(-1, 0, 2); - EXPECT_FLOAT_EQ(r, 0) << "Clamp -1 0 2"; + r = Float::Clamp(-1, 0, 2); + EXPECT_FLOAT_EQ(r, 0) << "Clamp -1 0 2"; - r = Float::Clamp(3, 0, 2); - EXPECT_FLOAT_EQ(r, 2) << "Clamp 3 0 2"; + r = Float::Clamp(3, 0, 2); + EXPECT_FLOAT_EQ(r, 2) << "Clamp 3 0 2"; - r = Float::Clamp(1, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Clamp 1 0 0"; + r = Float::Clamp(1, 0, 0); + EXPECT_FLOAT_EQ(r, 0) << "Clamp 1 0 0"; - r = Float::Clamp(0, 0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 0 0"; + r = Float::Clamp(0, 0, 0); + EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 0 0"; - r = Float::Clamp(0, 1, -1); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 0 1 -1"; + r = Float::Clamp(0, 1, -1); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 0 1 -1"; - if (std::numeric_limits::is_iec559) { - r = Float::Clamp(1, 0, FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 INFINITY"; + if (std::numeric_limits::is_iec559) { + r = Float::Clamp(1, 0, FLOAT_INFINITY); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 INFINITY"; - r = Float::Clamp(1, -FLOAT_INFINITY, 1); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 -INFINITY 1"; - } + r = Float::Clamp(1, -FLOAT_INFINITY, 1); + EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 -INFINITY 1"; + } } #endif \ No newline at end of file diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 9797969..a470593 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -62,7 +62,7 @@ TEST(Polar, FromSpherical) { p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; - EXPECT_FLOAT_EQ(p.angle.InDegrees(), 180.0F) + EXPECT_FLOAT_EQ(p.angle.InDegrees(), -180.0F) << "p.angle FromSpherical(-1 0 0)"; s = Spherical(0, Angle::Degrees(0), Angle::Degrees(90)); diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index cd8dcad..69226de 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -71,7 +71,7 @@ TEST(Spherical, FromPolar) { s = Spherical::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 180.0F) + EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), -180.0F) << "s.hor Polar(-1 0)"; EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(-1 0)"; From 8286c1ca85d28129dac572bf542e078a04f32288 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Sep 2024 09:33:14 +0200 Subject: [PATCH 099/121] Minor improvements --- Angle.cpp | 15 +++++++++++++-- Angle.h | 5 +++++ Direction.cpp | 33 +++++++++++++++++++-------------- SwingTwist.cpp | 8 +++----- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 5b71d0d..00ea7cb 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -76,9 +76,8 @@ AngleOf AngleOf::Degrees(float angle) { template <> AngleOf AngleOf::Radians(float angle) { - if (!isfinite(angle)) { + if (!isfinite(angle)) return AngleOf(0); - } // map float [-PI..PI) to integer [-32768..32767] signed short value = (signed short)(angle / pi * 32768.0F); @@ -130,6 +129,13 @@ float AngleOf::InRadians() const { //===== Generic +template +const AngleOf AngleOf::zero = AngleOf(); +template +const AngleOf AngleOf::deg90 = AngleOf::Degrees(90); +template +const AngleOf AngleOf::deg180 = AngleOf::Degrees(180); + template bool AngleOf::operator==(const AngleOf a) const { return this->value == a.value; @@ -267,6 +273,11 @@ AngleOf AngleOf::Atan(float f) { return AngleOf::Radians(atanf(f)); } +template +AngleOf Passer::LinearAlgebra::AngleOf::Atan2(float f1, float f2) { + return AngleOf::Radians(atan2f(f1, f2)); +} + // template <> // float AngleOf::CosineRuleSide(float a, float b, AngleOf gamma) // { diff --git a/Angle.h b/Angle.h index 59ba151..384c66f 100644 --- a/Angle.h +++ b/Angle.h @@ -21,6 +21,10 @@ class AngleOf { static AngleOf Degrees(float f); static AngleOf Radians(float f); + const static AngleOf zero; + const static AngleOf deg90; + const static AngleOf deg180; + float InDegrees() const; float InRadians() const; @@ -64,6 +68,7 @@ class AngleOf { static AngleOf Acos(float f); static AngleOf Asin(float f); static AngleOf Atan(float f); + static AngleOf Atan2(float f1, float f2); static float CosineRuleSide(float a, float b, AngleOf gamma); static AngleOf CosineRuleAngle(float a, float b, float c); diff --git a/Direction.cpp b/Direction.cpp index 8dc6bad..e4a26f9 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -24,8 +24,13 @@ DirectionOf::DirectionOf(AngleOf horizontal, AngleOf vertical) { template DirectionOf::DirectionOf(Vector3 v) { - this->horizontal = AngleOf::Radians(atan2f(v.Right(), v.Forward())); - this->vertical = AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); + this->horizontal = AngleOf::Atan2( + v.Right(), + v.Forward()); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); + this->vertical = + -AngleOf::deg90 - + AngleOf::Acos( + v.Up()); // AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); Normalize(); } @@ -34,19 +39,19 @@ const DirectionOf DirectionOf::forward = DirectionOf(AngleOf(), AngleOf()); template const DirectionOf DirectionOf::back = - DirectionOf(AngleOf::Degrees(180), AngleOf()); + DirectionOf(AngleOf::deg180, AngleOf()); template const DirectionOf DirectionOf::up = - DirectionOf(AngleOf(), AngleOf::Degrees(90)); + DirectionOf(AngleOf(), AngleOf::deg90); template const DirectionOf DirectionOf::down = - DirectionOf(AngleOf(), AngleOf::Degrees(-90)); + DirectionOf(AngleOf(), -AngleOf::deg90); template const DirectionOf DirectionOf::left = - DirectionOf(AngleOf::Degrees(-90), AngleOf()); + DirectionOf(-AngleOf::deg90, AngleOf()); template const DirectionOf DirectionOf::right = - DirectionOf(AngleOf::Degrees(90), AngleOf()); + DirectionOf(AngleOf::deg90, AngleOf()); template DirectionOf Passer::LinearAlgebra::DirectionOf::Degrees(float horizontal, @@ -70,14 +75,14 @@ bool Passer::LinearAlgebra::DirectionOf::operator==( template DirectionOf Passer::LinearAlgebra::DirectionOf::operator-() const { - DirectionOf r = DirectionOf(this->horizontal + AngleOf::Degrees(180), - -this->vertical); + DirectionOf r = + DirectionOf(this->horizontal + AngleOf::deg180, -this->vertical); return r; } template Vector3 DirectionOf::ToVector3() { - Vector3 v = Quaternion::Euler(-(this->vertical.InDegrees()), + Vector3 v = Quaternion::Euler(-this->vertical.InDegrees(), this->horizontal.InDegrees(), 0) * Vector3::forward; return v; @@ -85,10 +90,10 @@ Vector3 DirectionOf::ToVector3() { template void DirectionOf::Normalize() { - if (this->vertical > AngleOf::Degrees(90) || - this->vertical < AngleOf::Degrees(-90)) { - this->horizontal += AngleOf::Degrees(180); - this->vertical = AngleOf::Degrees(180) - this->vertical; + if (this->vertical > AngleOf::deg90 || + this->vertical < -AngleOf::deg90) { + this->horizontal += AngleOf::deg180; + this->vertical = AngleOf::deg180 - this->vertical; } } diff --git a/SwingTwist.cpp b/SwingTwist.cpp index a82097c..4d9fc1f 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -31,8 +31,7 @@ template SwingTwistOf SwingTwistOf::Degrees(float horizontal, float vertical, float twist) { - DirectionOf swing = DirectionOf(AngleOf::Degrees(horizontal), - AngleOf::Degrees(vertical)); + DirectionOf swing = DirectionOf::Degrees(horizontal, vertical); AngleOf twistAngle = AngleOf::Degrees(twist); SwingTwistOf orientation = SwingTwistOf(swing, twistAngle); return orientation; @@ -50,9 +49,8 @@ template SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromQuaternion( Quaternion q) { Vector3 angles = Quaternion::ToAngles(q); - SwingTwistOf r = SwingTwistOf(AngleOf::Degrees(angles.Up()), - AngleOf::Degrees(angles.Right()), - AngleOf::Degrees(angles.Forward())); + SwingTwistOf r = + SwingTwistOf::Degrees(angles.Up(), angles.Right(), angles.Forward()); return r; } From 54d03185b41b33b502f92ecec492983f2313b25c Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Sep 2024 10:10:28 +0200 Subject: [PATCH 100/121] Extended unit tests (plus fixes) --- AngleAxis.cpp | 4 +- CMakeLists.txt | 13 +--- Direction.cpp | 44 ++++++++++---- Direction.h | 5 +- Quaternion.cpp | 2 +- Quaternion.h | 51 ++++++++-------- SwingTwist.cpp | 20 +++++++ SwingTwist.h | 3 + Vector3.cpp | 2 +- Vector3.h | 2 +- test/Spherical16_test.cc | 12 ++++ ...erical_test.cc => SphericalSingle_test.cc} | 59 ++++++++++--------- test/SwingTwistSingle_test.cc | 46 +++++++++++++++ 13 files changed, 183 insertions(+), 80 deletions(-) rename test/{Spherical_test.cc => SphericalSingle_test.cc} (77%) create mode 100644 test/SwingTwistSingle_test.cc diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 54a5674..1ff8c0e 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -19,7 +19,7 @@ AngleAxisOf::AngleAxisOf(float angle, DirectionOf axis) { template AngleAxisOf::AngleAxisOf(float angle, Vector3 axis) { this->angle = angle; - this->axis = DirectionOf(axis); + this->axis = DirectionOf::FromVector3(axis); } template @@ -28,7 +28,7 @@ AngleAxisOf::AngleAxisOf(Quaternion q) { Vector3 axis; q.ToAngleAxis(&angle, &axis); this->angle = angle; - this->axis = DirectionOf(axis); + this->axis = DirectionOf::FromVector3(axis); } template diff --git a/CMakeLists.txt b/CMakeLists.txt index d57f009..6c50090 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,21 +40,10 @@ else() enable_testing() - file(GLOB_RECURSE test_srcs test/*.cc) + file(GLOB_RECURSE test_srcs test/*_test.cc) add_executable( LinearAlgebraTest ${test_srcs} - # "test/Angle_test.cc" - # "test/Direction_test.cc" - # "test/DiscreteAngle_test.cc" - # "test/FloatSingle_test.cc" - # "test/Matrix_test.cc" - # "test/Polar_test.cc" - # "test/Quaternion_test.cc" - # "test/Spherical_test.cc" - # "test/Spherical16_test.cc" - # "test/Vector2_test.cc" - # "test/Vector3_test.cc" ) target_link_libraries( LinearAlgebraTest diff --git a/Direction.cpp b/Direction.cpp index e4a26f9..8d83b47 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -22,17 +22,17 @@ DirectionOf::DirectionOf(AngleOf horizontal, AngleOf vertical) { Normalize(); }; -template -DirectionOf::DirectionOf(Vector3 v) { - this->horizontal = AngleOf::Atan2( - v.Right(), - v.Forward()); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); - this->vertical = - -AngleOf::deg90 - - AngleOf::Acos( - v.Up()); // AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); - Normalize(); -} +// template +// DirectionOf::DirectionOf(Vector3 v) { +// this->horizontal = AngleOf::Atan2( +// v.Right(), +// v.Forward()); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); +// this->vertical = +// -AngleOf::deg90 - +// AngleOf::Acos( +// v.Up()); // AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); +// Normalize(); +// } template const DirectionOf DirectionOf::forward = @@ -53,6 +53,28 @@ template const DirectionOf DirectionOf::right = DirectionOf(AngleOf::deg90, AngleOf()); +template +Vector3 Passer::LinearAlgebra::DirectionOf::ToVector3() const { + Quaternion q = Quaternion::Euler(-this->vertical.InDegrees(), + this->horizontal.InDegrees(), 0); + Vector3 v = q * Vector3::forward; + return v; +} + +template +DirectionOf Passer::LinearAlgebra::DirectionOf::FromVector3(Vector3 v) { + DirectionOf d; + d.horizontal = AngleOf::Atan2( + v.Right(), + v.Forward()); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); + d.vertical = + -AngleOf::deg90 - + AngleOf::Acos( + v.Up()); // AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); + d.Normalize(); + return d; +} + template DirectionOf Passer::LinearAlgebra::DirectionOf::Degrees(float horizontal, float vertical) { diff --git a/Direction.h b/Direction.h index 54faaac..5b5d0fb 100644 --- a/Direction.h +++ b/Direction.h @@ -22,7 +22,10 @@ class DirectionOf { DirectionOf(); DirectionOf(AngleOf horizontal, AngleOf vertical); - DirectionOf(Vector3 v); + // DirectionOf(Vector3 v); + + Vector3 ToVector3() const; + static DirectionOf FromVector3(Vector3 v); static DirectionOf Degrees(float horizontal, float vertical); static DirectionOf Radians(float horizontal, float vertical); diff --git a/Quaternion.cpp b/Quaternion.cpp index 67a761a..1a7352e 100644 --- a/Quaternion.cpp +++ b/Quaternion.cpp @@ -136,7 +136,7 @@ Vector3 Quaternion::operator*(const Vector3& p) const { return result; } -bool Quaternion::operator==(const Quaternion& q) { +bool Quaternion::operator==(const Quaternion& q) const { return (this->x == q.x && this->y == q.y && this->z == q.z && this->w == q.w); } diff --git a/Quaternion.h b/Quaternion.h index cc99a51..1979c76 100644 --- a/Quaternion.h +++ b/Quaternion.h @@ -39,7 +39,7 @@ typedef struct Quat { /// A quaternion /// struct Quaternion : Quat { -public: + public: /// /// Create a new identity quaternion /// @@ -80,7 +80,7 @@ public: /// A unit quaternion /// This will preserve the orientation, /// but ensures that it is a unit quaternion. - static Quaternion Normalize(const Quaternion &q); + static Quaternion Normalize(const Quaternion& q); /// /// Convert to euler angles @@ -88,14 +88,14 @@ public: /// The quaternion to convert /// A vector containing euler angles /// The euler angles performed in the order: Z, X, Y - static Vector3 ToAngles(const Quaternion &q); + static Vector3 ToAngles(const Quaternion& q); /// /// Rotate a vector using this quaterion /// /// The vector to rotate /// The rotated vector - Vector3 operator*(const Vector3 &vector) const; + Vector3 operator*(const Vector3& vector) const; /// /// Multiply this quaternion with another quaternion /// @@ -103,7 +103,7 @@ public: /// The resulting rotation /// The result will be this quaternion rotated according to /// the give rotation. - Quaternion operator*(const Quaternion &rotation) const; + Quaternion operator*(const Quaternion& rotation) const; /// /// Check the equality of two quaternions @@ -114,7 +114,7 @@ public: /// themselves. Two quaternions with the same rotational effect may have /// different components. Use Quaternion::Angle to check if the rotations are /// the same. - bool operator==(const Quaternion &quaternion); + bool operator==(const Quaternion& quaternion) const; /// /// The inverse of quaterion @@ -129,8 +129,8 @@ public: /// The look direction /// The up direction /// The look rotation - static Quaternion LookRotation(const Vector3 &forward, - const Vector3 &upwards); + static Quaternion LookRotation(const Vector3& forward, + const Vector3& upwards); /// /// Creates a quaternion with the given forward direction with up = /// Vector3::up @@ -140,7 +140,7 @@ public: /// For the rotation, Vector::up is used for the up direction. /// Note: if the forward direction == Vector3::up, the result is /// Quaternion::identity - static Quaternion LookRotation(const Vector3 &forward); + static Quaternion LookRotation(const Vector3& forward); /// /// Calculat the rotation from on vector to another @@ -157,7 +157,8 @@ public: /// The destination rotation /// The maximum amount of degrees to /// rotate The possibly limited rotation - static Quaternion RotateTowards(const Quaternion &from, const Quaternion &to, + static Quaternion RotateTowards(const Quaternion& from, + const Quaternion& to, float maxDegreesDelta); /// @@ -166,13 +167,13 @@ public: /// The angle /// The axis /// The resulting quaternion - static Quaternion AngleAxis(float angle, const Vector3 &axis); + static Quaternion AngleAxis(float angle, const Vector3& axis); /// /// Convert this quaternion to angle/axis representation /// /// A pointer to the angle for the result /// A pointer to the axis for the result - void ToAngleAxis(float *angle, Vector3 *axis); + void ToAngleAxis(float* angle, Vector3* axis); /// /// Get the angle between two orientations @@ -190,8 +191,9 @@ public: /// The factor between 0 and 1. /// The resulting rotation /// A factor 0 returns rotation1, factor1 returns rotation2. - static Quaternion Slerp(const Quaternion &rotation1, - const Quaternion &rotation2, float factor); + static Quaternion Slerp(const Quaternion& rotation1, + const Quaternion& rotation2, + float factor); /// /// Unclamped sherical lerp between two rotations /// @@ -201,8 +203,9 @@ public: /// The resulting rotation /// A factor 0 returns rotation1, factor1 returns rotation2. /// Values outside the 0..1 range will result in extrapolated rotations - static Quaternion SlerpUnclamped(const Quaternion &rotation1, - const Quaternion &rotation2, float factor); + static Quaternion SlerpUnclamped(const Quaternion& rotation1, + const Quaternion& rotation2, + float factor); /// /// Create a rotation from euler angles @@ -260,8 +263,10 @@ public: /// A pointer to the quaternion for the swing /// result A pointer to the quaternion for the /// twist result - static void GetSwingTwist(Vector3 axis, Quaternion rotation, - Quaternion *swing, Quaternion *twist); + static void GetSwingTwist(Vector3 axis, + Quaternion rotation, + Quaternion* swing, + Quaternion* twist); /// /// Calculate the dot product of two quaternions @@ -271,20 +276,20 @@ public: /// static float Dot(Quaternion rotation1, Quaternion rotation2); -private: + private: float GetLength() const; float GetLengthSquared() const; - static float GetLengthSquared(const Quaternion &q); + static float GetLengthSquared(const Quaternion& q); - void ToAxisAngleRad(const Quaternion &q, Vector3 *const axis, float *angle); + void ToAxisAngleRad(const Quaternion& q, Vector3* const axis, float* angle); static Quaternion FromEulerRad(Vector3 euler); static Quaternion FromEulerRadXYZ(Vector3 euler); Vector3 xyz() const; }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #endif diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 4d9fc1f..aeba4cc 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -55,6 +55,26 @@ SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromQuaternion( return r; } +template +SphericalOf Passer::LinearAlgebra::SwingTwistOf::ToAngleAxis() const { + Quaternion q = this->ToQuaternion(); + float angle; + Vector3 axis; + q.ToAngleAxis(&angle, &axis); + DirectionOf direction = DirectionOf::FromVector3(axis); + + SphericalOf aa = SphericalOf(angle, direction); + return aa; +} + +template +SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromAngleAxis( + SphericalOf aa) { + Vector3 vectorAxis = aa.direction.ToVector3(); + Quaternion q = Quaternion::AngleAxis(aa.distance, vectorAxis); + return SwingTwistOf(); +} + template const SwingTwistOf SwingTwistOf::identity = SwingTwistOf(); diff --git a/SwingTwist.h b/SwingTwist.h index 37cfede..e5b43a4 100644 --- a/SwingTwist.h +++ b/SwingTwist.h @@ -29,6 +29,9 @@ class SwingTwistOf { Quaternion ToQuaternion() const; static SwingTwistOf FromQuaternion(Quaternion q); + SphericalOf ToAngleAxis() const; + static SwingTwistOf FromAngleAxis(SphericalOf aa); + const static SwingTwistOf identity; /// diff --git a/Vector3.cpp b/Vector3.cpp index 958fdaf..e3f1b8e 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -153,7 +153,7 @@ float Vector3::Dot(const Vector3& v1, const Vector3& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } -bool Vector3::operator==(const Vector3& v) { +bool Vector3::operator==(const Vector3& v) const { return (this->x == v.x && this->y == v.y && this->z == v.z); } diff --git a/Vector3.h b/Vector3.h index b480d20..bb3d4b7 100644 --- a/Vector3.h +++ b/Vector3.h @@ -90,7 +90,7 @@ struct Vector3 : Vec3 { /// @return true if it is identical to the given vector /// @note This uses float comparison to check equality which may have strange /// effects. Equality on floats should be avoided. - bool operator==(const Vector3& v); + bool operator==(const Vector3& v) const; /// @brief The vector length /// @param v The vector for which you need the length diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index 4f445c9..2e398e5 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -33,6 +33,18 @@ TEST(Spherical16, FromVector3) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; } +TEST(Spherical16, Vector3) { + Vector3 v = Vector3(1, 2, 3); + Spherical16 rd = Spherical16::FromVector3(v); + Vector3 rv = rd.ToVector3(); + EXPECT_LT(Vector3::Distance(v, rv), 10e-4) << " 1 2 3 <-> spherical"; + + v = Vector3(1, 2, -3); + rd = Spherical16::FromVector3(v); + rv = rd.ToVector3(); + EXPECT_LT(Vector3::Distance(v, rv), 10e-4) << " 1 2 3 <-> spherical"; +} + // TEST(Spherical16, FromPolar) { // Polar p = Polar(1, 0); // Spherical16 s = Spherical16::FromPolar(p); diff --git a/test/Spherical_test.cc b/test/SphericalSingle_test.cc similarity index 77% rename from test/Spherical_test.cc rename to test/SphericalSingle_test.cc index 69226de..db68c37 100644 --- a/test/Spherical_test.cc +++ b/test/SphericalSingle_test.cc @@ -7,32 +7,32 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() -TEST(Spherical, FromVector3) { +TEST(SphericalSingle, FromVector3) { Vector3 v = Vector3(0, 0, 1); - Spherical s = Spherical::FromVector3(v); + SphericalSingle s = SphericalSingle ::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 0 1"; EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; v = Vector3(0, 1, 0); - s = Spherical::FromVector3(v); + s = SphericalSingle ::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; v = Vector3(1, 0, 0); - s = Spherical::FromVector3(v); + s = SphericalSingle ::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; } -TEST(Spherical, FromPolar) { +TEST(SphericalSingle, FromPolar) { Polar p = Polar(1, Angle::Degrees(0)); - Spherical s = Spherical::FromPolar(p); + SphericalSingle s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) @@ -41,7 +41,7 @@ TEST(Spherical, FromPolar) { << "s.vert Polar(1 0)"; p = Polar(1, Angle::Degrees(45)); - s = Spherical::FromPolar(p); + s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 45.0F) @@ -50,7 +50,7 @@ TEST(Spherical, FromPolar) { << "s.vert Polar(1 45)"; p = Polar(1, Angle::Degrees(-45)); - s = Spherical::FromPolar(p); + s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), -45.0F) @@ -59,7 +59,7 @@ TEST(Spherical, FromPolar) { << "s.vert Polar(1 -45)"; p = Polar(0, Angle::Degrees(0)); - s = Spherical::FromPolar(p); + s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) @@ -68,7 +68,7 @@ TEST(Spherical, FromPolar) { << "s.vert Polar(0 0)"; p = Polar(-1, Angle::Degrees(0)); - s = Spherical::FromPolar(p); + s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), -180.0F) @@ -77,12 +77,12 @@ TEST(Spherical, FromPolar) { << "s.vert Polar(-1 0)"; } -TEST(Spherical, Incident1) { +TEST(SphericalSingle, Incident1) { Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); - Spherical s = Spherical::FromVector3(v); + SphericalSingle s = SphericalSingle ::FromVector3(v); - Spherical sr = - Spherical(2.49F, Angle::Degrees(98.18f), Angle::Degrees(24.4F)); + SphericalSingle sr = + SphericalSingle(2.49F, Angle::Degrees(98.18f), Angle::Degrees(24.4F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-02); @@ -95,12 +95,12 @@ TEST(Spherical, Incident1) { EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0"; } -TEST(Spherical, Incident2) { +TEST(SphericalSingle, Incident2) { Vector3 v = Vector3(1.0f, 0.0f, 1.0f); - Spherical s = Spherical::FromVector3(v); + SphericalSingle s = SphericalSingle ::FromVector3(v); - Spherical sr = - Spherical(1.4142135623F, Angle::Degrees(45.0f), Angle::Degrees(0.0F)); + SphericalSingle sr = SphericalSingle(1.4142135623F, Angle::Degrees(45.0f), + Angle::Degrees(0.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-05); @@ -113,9 +113,10 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(0.0f, 1.0f, 1.0f); - s = Spherical::FromVector3(v); + s = SphericalSingle ::FromVector3(v); - sr = Spherical(1.4142135623F, Angle::Degrees(0.0f), Angle::Degrees(45.0F)); + sr = SphericalSingle(1.4142135623F, Angle::Degrees(0.0f), + Angle::Degrees(45.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-05); @@ -128,7 +129,7 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); - s = Spherical::FromVector3(v); + s = SphericalSingle ::FromVector3(v); r = Vector3(s); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); @@ -139,17 +140,19 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); - // s = Spherical(10, 45, 45); + // s = SphericalSingle + (10, 45, 45); // r = s.ToVector3(); // EXPECT_NEAR(r.x, 5, 1.0e-06); // EXPECT_NEAR(r.y, 7.07, 1.0e-06); // EXPECT_NEAR(r.z, 5, 1.0e-06); } -TEST(Spherical, Addition) { - Spherical v1 = Spherical(1, Angle::Degrees(45), Angle::Degrees(0)); - Spherical v2 = Spherical::zero; - Spherical r = Spherical::zero; +TEST(SphericalSingle, Addition) { + SphericalSingle v1 = + SphericalSingle(1, Angle::Degrees(45), Angle::Degrees(0)); + SphericalSingle v2 = SphericalSingle ::zero; + SphericalSingle r = SphericalSingle ::zero; r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; @@ -158,13 +161,13 @@ TEST(Spherical, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; - v2 = Spherical(1, Angle::Degrees(-45), Angle::Degrees(0)); + v2 = SphericalSingle(1, Angle::Degrees(-45), Angle::Degrees(0)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; - v2 = Spherical(1, Angle::Degrees(0), Angle::Degrees(90)); + v2 = SphericalSingle(1, Angle::Degrees(0), Angle::Degrees(90)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; diff --git a/test/SwingTwistSingle_test.cc b/test/SwingTwistSingle_test.cc new file mode 100644 index 0000000..49040e3 --- /dev/null +++ b/test/SwingTwistSingle_test.cc @@ -0,0 +1,46 @@ +#if GTEST +#include +#include +#include + +#include "SwingTwist.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(SwingTwistSingle, Quaternion) { + Quaternion q; + SwingTwistSingle s; + Quaternion rq; + + q = Quaternion::identity; + s = SwingTwistSingle::FromQuaternion(q); + rq = s.ToQuaternion(); + EXPECT_EQ(q, rq) << " 0 0 0 1 <-> SwingTwist"; + + q = Quaternion::Euler(90, 0, 0); + s = SwingTwistSingle::FromQuaternion(q); + rq = s.ToQuaternion(); + EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 90 0 0 <-> SwingTwist"; + + q = Quaternion::Euler(0, 90, 0); + s = SwingTwistSingle::FromQuaternion(q); + rq = s.ToQuaternion(); + EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 0 90 0 <-> SwingTwist"; + + q = Quaternion::Euler(0, 0, 90); + s = SwingTwistSingle::FromQuaternion(q); + rq = s.ToQuaternion(); + EXPECT_EQ(q, rq) << " Euler 0 0 90 <-> SwingTwist"; + + q = Quaternion::Euler(0, 180, 0); // ==> spherical S(180 0)T0 + s = SwingTwistSingle::FromQuaternion(q); + rq = s.ToQuaternion(); + EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 0 90 0 <-> SwingTwist"; + + q = Quaternion::Euler(0, 135, 0); // ==> spherical S(180 45)T0 + s = SwingTwistSingle::FromQuaternion(q); + rq = s.ToQuaternion(); + EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 0 90 0 <-> SwingTwist"; +} + +#endif \ No newline at end of file From 2e61e1b710cb0c0455d80970b7d072d70db7ac83 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Sep 2024 10:53:59 +0200 Subject: [PATCH 101/121] Fix unit test --- test/SphericalSingle_test.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/SphericalSingle_test.cc b/test/SphericalSingle_test.cc index db68c37..3e73e51 100644 --- a/test/SphericalSingle_test.cc +++ b/test/SphericalSingle_test.cc @@ -140,8 +140,7 @@ TEST(SphericalSingle, Incident2) { EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); - // s = SphericalSingle - (10, 45, 45); + // s = SphericalSingle(10, 45, 45); // r = s.ToVector3(); // EXPECT_NEAR(r.x, 5, 1.0e-06); // EXPECT_NEAR(r.y, 7.07, 1.0e-06); From 06da9e5b80d1336fb01a2eed43dde7cf46f22040 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Sep 2024 12:14:55 +0200 Subject: [PATCH 102/121] Removed AngleAxis, Sperhical will be used instead --- AngleAxis.cpp | 2 ++ AngleAxis.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/AngleAxis.cpp b/AngleAxis.cpp index 1ff8c0e..6e17e51 100644 --- a/AngleAxis.cpp +++ b/AngleAxis.cpp @@ -1,3 +1,4 @@ +/* // 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/. @@ -49,3 +50,4 @@ DirectionOf AngleAxisOf::GetSwing() { template class AngleAxisOf; template class AngleAxisOf; +*/ \ No newline at end of file diff --git a/AngleAxis.h b/AngleAxis.h index 821e774..4d51c30 100644 --- a/AngleAxis.h +++ b/AngleAxis.h @@ -1,3 +1,4 @@ +/* // 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/. @@ -40,4 +41,5 @@ using AngleAxis = AngleAxisOf; } // namespace Passer using namespace Passer::LinearAlgebra; -#endif \ No newline at end of file +#endif +*/ \ No newline at end of file From 9406b5755848d6d63eb57a433bd025f5c817e7ae Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Sep 2024 12:29:04 +0200 Subject: [PATCH 103/121] SwingTwist::AngleAxis using Direction --- SwingTwist.cpp | 8 +++----- SwingTwist.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/SwingTwist.cpp b/SwingTwist.cpp index aeba4cc..0971b78 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -105,17 +105,15 @@ SwingTwistOf SwingTwistOf::operator*=(const SwingTwistOf& rotation) { } template -SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::Inverse( - SwingTwistOf rotation) { +SwingTwistOf SwingTwistOf::Inverse(SwingTwistOf rotation) { SwingTwistOf r = SwingTwistOf( -rotation.swing.horizontal, -rotation.swing.vertical, -rotation.twist); return r; } template -SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::AngleAxis( - float angle, - const SphericalOf& axis) { +SwingTwistOf SwingTwistOf::AngleAxis(float angle, + const DirectionOf& axis) { Vector3 axis_vector = axis.ToVector3(); Quaternion q = Quaternion::AngleAxis(angle, axis_vector); SwingTwistOf r = SwingTwistOf::FromQuaternion(q); diff --git a/SwingTwist.h b/SwingTwist.h index e5b43a4..d5e27a0 100644 --- a/SwingTwist.h +++ b/SwingTwist.h @@ -58,7 +58,7 @@ class SwingTwistOf { /// The angle /// The axis /// The resulting quaternion - static SwingTwistOf AngleAxis(float angle, const SphericalOf& axis); + static SwingTwistOf AngleAxis(float angle, const DirectionOf& axis); }; using SwingTwistSingle = SwingTwistOf; From 0a07b23e96e7c629f120ffbe2a00e02d2e193ac0 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Sep 2024 12:53:59 +0200 Subject: [PATCH 104/121] SwingTwist == and Angle --- Angle.cpp | 8 +- Angle.h | 8 +- Direction.h | 1 - SwingTwist.cpp | 25 ++-- SwingTwist.h | 5 + test/Angle_test.cc | 224 ---------------------------------- test/SwingTwistSingle_test.cc | 52 ++++++++ 7 files changed, 83 insertions(+), 240 deletions(-) delete mode 100644 test/Angle_test.cc diff --git a/Angle.cpp b/Angle.cpp index 00ea7cb..4588736 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -142,22 +142,22 @@ bool AngleOf::operator==(const AngleOf a) const { } template -bool AngleOf::operator>(AngleOf a) { +bool AngleOf::operator>(AngleOf a) const { return this->value > a.value; } template -bool AngleOf::operator>=(AngleOf a) { +bool AngleOf::operator>=(AngleOf a) const { return this->value >= a.value; } template -bool AngleOf::operator<(AngleOf a) { +bool AngleOf::operator<(AngleOf a) const { return this->value < a.value; } template -bool AngleOf::operator<=(AngleOf a) { +bool AngleOf::operator<=(AngleOf a) const { return this->value <= a.value; } diff --git a/Angle.h b/Angle.h index 384c66f..8b02505 100644 --- a/Angle.h +++ b/Angle.h @@ -31,10 +31,10 @@ class AngleOf { inline T GetBinary() const { return this->value; } bool operator==(const AngleOf a) const; - bool operator>(AngleOf a); - bool operator>=(AngleOf a); - bool operator<(AngleOf a); - bool operator<=(AngleOf a); + bool operator>(AngleOf a) const; + bool operator>=(AngleOf a) const; + bool operator<(AngleOf a) const; + bool operator<=(AngleOf a) const; static signed int Sign(AngleOf a); static AngleOf Abs(AngleOf a); diff --git a/Direction.h b/Direction.h index 5b5d0fb..79ca814 100644 --- a/Direction.h +++ b/Direction.h @@ -22,7 +22,6 @@ class DirectionOf { DirectionOf(); DirectionOf(AngleOf horizontal, AngleOf vertical); - // DirectionOf(Vector3 v); Vector3 ToVector3() const; static DirectionOf FromVector3(Vector3 v); diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 0971b78..459efee 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -11,8 +11,7 @@ SwingTwistOf::SwingTwistOf() { } template -Passer::LinearAlgebra::SwingTwistOf::SwingTwistOf(DirectionOf swing, - AngleOf twist) { +SwingTwistOf::SwingTwistOf(DirectionOf swing, AngleOf twist) { this->swing = swing; this->twist = twist; } @@ -46,8 +45,7 @@ Quaternion SwingTwistOf::ToQuaternion() const { } template -SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromQuaternion( - Quaternion q) { +SwingTwistOf SwingTwistOf::FromQuaternion(Quaternion q) { Vector3 angles = Quaternion::ToAngles(q); SwingTwistOf r = SwingTwistOf::Degrees(angles.Up(), angles.Right(), angles.Forward()); @@ -56,7 +54,7 @@ SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromQuaternion( } template -SphericalOf Passer::LinearAlgebra::SwingTwistOf::ToAngleAxis() const { +SphericalOf SwingTwistOf::ToAngleAxis() const { Quaternion q = this->ToQuaternion(); float angle; Vector3 axis; @@ -68,13 +66,17 @@ SphericalOf Passer::LinearAlgebra::SwingTwistOf::ToAngleAxis() const { } template -SwingTwistOf Passer::LinearAlgebra::SwingTwistOf::FromAngleAxis( - SphericalOf aa) { +SwingTwistOf SwingTwistOf::FromAngleAxis(SphericalOf aa) { Vector3 vectorAxis = aa.direction.ToVector3(); Quaternion q = Quaternion::AngleAxis(aa.distance, vectorAxis); return SwingTwistOf(); } +template +bool SwingTwistOf::operator==(const SwingTwistOf s) const { + return (this->swing == s.swing) && (this->twist == s.twist); +} + template const SwingTwistOf SwingTwistOf::identity = SwingTwistOf(); @@ -120,5 +122,14 @@ SwingTwistOf SwingTwistOf::AngleAxis(float angle, return r; } +template +AngleOf SwingTwistOf::Angle(const SwingTwistOf& r1, + const SwingTwistOf& r2) { + Quaternion q1 = r1.ToQuaternion(); + Quaternion q2 = r2.ToQuaternion(); + float angle = Quaternion::Angle(q1, q2); + return AngleOf::Degrees(angle); +} + template class SwingTwistOf; template class SwingTwistOf; \ No newline at end of file diff --git a/SwingTwist.h b/SwingTwist.h index d5e27a0..0558bbb 100644 --- a/SwingTwist.h +++ b/SwingTwist.h @@ -26,6 +26,7 @@ class SwingTwistOf { static SwingTwistOf Degrees(float horizontal, float vertical = 0, float twist = 0); + Quaternion ToQuaternion() const; static SwingTwistOf FromQuaternion(Quaternion q); @@ -34,6 +35,8 @@ class SwingTwistOf { const static SwingTwistOf identity; + bool operator==(const SwingTwistOf d) const; + /// /// Rotate a vector using this rotation /// @@ -59,6 +62,8 @@ class SwingTwistOf { /// The axis /// The resulting quaternion static SwingTwistOf AngleAxis(float angle, const DirectionOf& axis); + + static AngleOf Angle(const SwingTwistOf& r1, const SwingTwistOf& r2); }; using SwingTwistSingle = SwingTwistOf; diff --git a/test/Angle_test.cc b/test/Angle_test.cc deleted file mode 100644 index 6cda76e..0000000 --- a/test/Angle_test.cc +++ /dev/null @@ -1,224 +0,0 @@ -/* -#if GTEST -#include - -#include -#include - -#include "Angle.h" - -#define FLOAT_INFINITY std::numeric_limits::infinity() - -TEST(Angle16, Compare) { - Angle16 a = Angle16::Degrees(45); - bool r = false; - - r = a > Angle16::Degrees(0); - EXPECT_TRUE(r) << "45 > 0"; - - r = a > Angle16::Degrees(90); - EXPECT_FALSE(r) << "45 > 90"; - - r = a > Angle16::Degrees(-90); - EXPECT_TRUE(r) << "45 > -90"; -} - -TEST(AngleSingle, Compare) { - AngleSingle a = AngleSingle::Degrees(45); - bool r = false; - - r = a > AngleSingle::Degrees(0); - EXPECT_TRUE(r) << "45 > 0"; - - r = a > AngleSingle::Degrees(90); - EXPECT_FALSE(r) << "45 > 90"; - - r = a > AngleSingle::Degrees(-90); - EXPECT_TRUE(r) << "45 > -90"; -} - -TEST(Angle, Normalize) { - Angle r = AngleSingle(); - - r = Angle::Normalize(AngleSingle::Degrees(90.0f)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize 90"; - - r = Angle::Normalize(AngleSingle::Degrees(-90)); - EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize -90"; - - r = Angle::Normalize(AngleSingle::Degrees(270)); - EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270"; - - r = Angle::Normalize(AngleSingle::Degrees(270 + 360)); - EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Normalize 270+360"; - - r = Angle::Normalize(AngleSingle::Degrees(-270)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270"; - - r = Angle::Normalize(AngleSingle::Degrees(-270 - 360)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize -270-360"; - - r = Angle::Normalize(AngleSingle::Degrees(0)); - EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Normalize 0"; - - if (std::numeric_limits::is_iec559) { - r = Angle::Normalize(AngleSingle::Degrees(FLOAT_INFINITY)); - EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "Normalize INFINITY"; - - r = Angle::Normalize(AngleSingle::Degrees(-FLOAT_INFINITY)); - EXPECT_FLOAT_EQ(r.InDegrees(), -FLOAT_INFINITY) << "Normalize INFINITY"; - } -} - -TEST(Angle, Clamp) { - Angle r = AngleSingle(); - - r = Angle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), - AngleSingle::Degrees(2)); - EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 0 2"; - - r = Angle::Clamp(AngleSingle::Degrees(-1), AngleSingle::Degrees(0), - AngleSingle::Degrees(2)); - EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp -1 0 2"; - - r = Angle::Clamp(AngleSingle::Degrees(3), AngleSingle::Degrees(0), - AngleSingle::Degrees(2)); - EXPECT_FLOAT_EQ(r.InDegrees(), 2) << "Clamp 3 0 2"; - - r = Angle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), - AngleSingle::Degrees(0)); - EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 1 0 0"; - - r = Angle::Clamp(AngleSingle::Degrees(0), AngleSingle::Degrees(0), - AngleSingle::Degrees(0)); - EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 0 0"; - - r = Angle::Clamp(AngleSingle::Degrees(0), AngleSingle::Degrees(1), - AngleSingle::Degrees(-1)); - EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 0 1 -1"; - - if (std::numeric_limits::is_iec559) { - r = Angle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), - AngleSingle::Degrees(FLOAT_INFINITY)); - EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 0 INFINITY"; - - r = Angle::Clamp(AngleSingle::Degrees(1), - AngleSingle::Degrees(-FLOAT_INFINITY), - AngleSingle::Degrees(1)); - EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 1 -INFINITY 1"; - } -} - -// TEST(Angle, Difference) { -// Angle r = 0; - -// r = Angle::Difference(0, 90); -// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 90"; - -// r = Angle::Difference(0, -90); -// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 -90"; - -// r = Angle::Difference(0, 270); -// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 0 270"; - -// r = Angle::Difference(0, -270); -// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 -270"; - -// r = Angle::Difference(90, 0); -// EXPECT_FLOAT_EQ(r.InDegrees(), -90) << "Difference 90 0"; - -// r = Angle::Difference(-90, 0); -// EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference -90 0"; - -// r = Angle::Difference(0, 0); -// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 0 0"; - -// r = Angle::Difference(90, 90); -// EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Difference 90 90"; - -// if (std::numeric_limits::is_iec559) { -// r = Angle::Difference(0, INFINITY); -// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference 0 INFINITY"; - -// r = Angle::Difference(0, -INFINITY); -// EXPECT_FLOAT_EQ(r.InDegrees(), -INFINITY) << "Difference 0 -INFINITY"; - -// r = Angle::Difference(-INFINITY, INFINITY); -// EXPECT_FLOAT_EQ(r.InDegrees(), INFINITY) << "Difference -INFINITY -// INFINITY"; -// } -// } - -TEST(Angle, MoveTowards) { - Angle r = Angle(); - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), - Angle::Degrees(30)); - EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 90 30"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), - Angle::Degrees(90)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 90"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), - Angle::Degrees(180)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 180"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), - Angle::Degrees(270)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 270"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), - Angle::Degrees(-30)); - EXPECT_FLOAT_EQ(r.InDegrees(), -30) << "MoveTowards 0 90 -30"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), - Angle::Degrees(-30)); - EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 -90 -30"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), - Angle::Degrees(-90)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 -90 -90"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), - Angle::Degrees(-180)); - EXPECT_FLOAT_EQ(r.InDegrees(), 180) << "MoveTowards 0 -90 -180"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), - Angle::Degrees(-270)); - EXPECT_FLOAT_EQ(r.InDegrees(), 270) << "MoveTowards 0 -90 -270"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), - Angle::Degrees(0)); - EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 90 0"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(0), - Angle::Degrees(0)); - EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 0"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(0), - Angle::Degrees(30)); - EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 30"; - - if (std::numeric_limits::is_iec559) { - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(90), - Angle::Degrees(FLOAT_INFINITY)); - EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "MoveTowards 0 90 FLOAT_INFINITY"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(FLOAT_INFINITY), - Angle::Degrees(30)); - EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 FLOAT_INFINITY 30"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-90), - Angle::Degrees(-FLOAT_INFINITY)); - EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) - << "MoveTowards 0 -90 -FLOAT_INFINITY"; - - r = Angle::MoveTowards(Angle::Degrees(0), Angle::Degrees(-FLOAT_INFINITY), - Angle::Degrees(-30)); - EXPECT_FLOAT_EQ(r.InDegrees(), 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; - } -} - -#endif -*/ \ No newline at end of file diff --git a/test/SwingTwistSingle_test.cc b/test/SwingTwistSingle_test.cc index 49040e3..5ed238b 100644 --- a/test/SwingTwistSingle_test.cc +++ b/test/SwingTwistSingle_test.cc @@ -43,4 +43,56 @@ TEST(SwingTwistSingle, Quaternion) { EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 0 90 0 <-> SwingTwist"; } +TEST(SwingTwistSingle, AngleAxis) { + SwingTwistSingle s; + SwingTwistSingle r; + + s = SwingTwistSingle::AngleAxis(0, DirectionSingle::up); + EXPECT_EQ(s, SwingTwistSingle::Degrees(0, 0, 0)) << "0 up"; + + r = SwingTwistSingle::AngleAxis(90, DirectionSingle::up); + s = SwingTwistSingle::Degrees(90, 0, 0); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "90 up"; + + r = SwingTwistSingle::AngleAxis(180, DirectionSingle::up); + s = SwingTwistSingle::Degrees(180, 0, 0); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "180 up"; + + r = SwingTwistSingle::AngleAxis(270, DirectionSingle::up); + s = SwingTwistSingle::Degrees(-90, 0, 0); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "270 up"; + + r = SwingTwistSingle::AngleAxis(90, DirectionSingle::right); + s = SwingTwistSingle::Degrees(0, 90, 0); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "90 right"; + + r = SwingTwistSingle::AngleAxis(180, DirectionSingle::right); + s = SwingTwistSingle::Degrees(0, 180, 0); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "180 right"; + r = SwingTwistSingle::AngleAxis(270, DirectionSingle::right); + s = SwingTwistSingle::Degrees(0, -90, 0); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "270 right"; + + r = SwingTwistSingle::AngleAxis(90, DirectionSingle::forward); + s = SwingTwistSingle::Degrees(0, 0, 90); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "90 up"; + + r = SwingTwistSingle::AngleAxis(180, DirectionSingle::forward); + s = SwingTwistSingle::Degrees(0, 0, 180); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "180 up"; + + r = SwingTwistSingle::AngleAxis(270, DirectionSingle::forward); + s = SwingTwistSingle::Degrees(0, 0, -90); + EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + << "270 up"; +} + #endif \ No newline at end of file From edbb4b1ffc928523ff973c0769abd45672c08e53 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 27 Sep 2024 09:44:06 +0200 Subject: [PATCH 105/121] Removes Angle::deg90/180 because of issues --- Angle.cpp | 12 ++++++------ Angle.h | 6 +++--- Direction.cpp | 24 ++++++++++++------------ test/SwingTwistSingle_test.cc | 5 +++++ 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 4588736..7788047 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -129,12 +129,12 @@ float AngleOf::InRadians() const { //===== Generic -template -const AngleOf AngleOf::zero = AngleOf(); -template -const AngleOf AngleOf::deg90 = AngleOf::Degrees(90); -template -const AngleOf AngleOf::deg180 = AngleOf::Degrees(180); +// template +// const AngleOf AngleOf::zero = AngleOf(); +// template +// const AngleOf AngleOf::deg90 = AngleOf::Degrees(90); +// template +// const AngleOf AngleOf::deg180 = AngleOf::Degrees(180); template bool AngleOf::operator==(const AngleOf a) const { diff --git a/Angle.h b/Angle.h index 8b02505..90531ab 100644 --- a/Angle.h +++ b/Angle.h @@ -21,9 +21,9 @@ class AngleOf { static AngleOf Degrees(float f); static AngleOf Radians(float f); - const static AngleOf zero; - const static AngleOf deg90; - const static AngleOf deg180; + // const static AngleOf zero; + // const static AngleOf deg90; + // const static AngleOf deg180; float InDegrees() const; float InRadians() const; diff --git a/Direction.cpp b/Direction.cpp index 8d83b47..882ea32 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -39,19 +39,19 @@ const DirectionOf DirectionOf::forward = DirectionOf(AngleOf(), AngleOf()); template const DirectionOf DirectionOf::back = - DirectionOf(AngleOf::deg180, AngleOf()); + DirectionOf(AngleOf::Degrees(180), AngleOf()); template const DirectionOf DirectionOf::up = - DirectionOf(AngleOf(), AngleOf::deg90); + DirectionOf(AngleOf(), AngleOf::Degrees(90)); template const DirectionOf DirectionOf::down = - DirectionOf(AngleOf(), -AngleOf::deg90); + DirectionOf(AngleOf(), AngleOf::Degrees(-90)); template const DirectionOf DirectionOf::left = - DirectionOf(-AngleOf::deg90, AngleOf()); + DirectionOf(AngleOf::Degrees(-90), AngleOf()); template const DirectionOf DirectionOf::right = - DirectionOf(AngleOf::deg90, AngleOf()); + DirectionOf(AngleOf::Degrees(90), AngleOf()); template Vector3 Passer::LinearAlgebra::DirectionOf::ToVector3() const { @@ -68,7 +68,7 @@ DirectionOf Passer::LinearAlgebra::DirectionOf::FromVector3(Vector3 v) { v.Right(), v.Forward()); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); d.vertical = - -AngleOf::deg90 - + AngleOf::Degrees(-90) - AngleOf::Acos( v.Up()); // AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); d.Normalize(); @@ -97,8 +97,8 @@ bool Passer::LinearAlgebra::DirectionOf::operator==( template DirectionOf Passer::LinearAlgebra::DirectionOf::operator-() const { - DirectionOf r = - DirectionOf(this->horizontal + AngleOf::deg180, -this->vertical); + DirectionOf r = DirectionOf(this->horizontal + AngleOf::Degrees(180), + -this->vertical); return r; } @@ -112,10 +112,10 @@ Vector3 DirectionOf::ToVector3() { template void DirectionOf::Normalize() { - if (this->vertical > AngleOf::deg90 || - this->vertical < -AngleOf::deg90) { - this->horizontal += AngleOf::deg180; - this->vertical = AngleOf::deg180 - this->vertical; + if (this->vertical > AngleOf::Degrees(90) || + this->vertical < AngleOf::Degrees(-90)) { + this->horizontal += AngleOf::Degrees(180); + this->vertical = AngleOf::Degrees(180) - this->vertical; } } diff --git a/test/SwingTwistSingle_test.cc b/test/SwingTwistSingle_test.cc index 5ed238b..14f4b81 100644 --- a/test/SwingTwistSingle_test.cc +++ b/test/SwingTwistSingle_test.cc @@ -93,6 +93,11 @@ TEST(SwingTwistSingle, AngleAxis) { s = SwingTwistSingle::Degrees(0, 0, -90); EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) << "270 up"; + + auto r16 = SwingTwist16::AngleAxis(13, Direction16::down); + auto s16 = SwingTwist16::Degrees(-13, 0, 0); + EXPECT_LT(SwingTwist16::Angle(r16, s16), Angle16::Degrees(10e-2f)) + << "270 up"; } #endif \ No newline at end of file From 06e42c5b9fa6b72ecafc08576d4b5c9fea0306c2 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 27 Sep 2024 15:40:10 +0200 Subject: [PATCH 106/121] Normalized swing twist --- Angle.cpp | 20 ++++++++++++++++ Angle.h | 1 + Direction.cpp | 12 ---------- SwingTwist.cpp | 45 ++++++++++++++++++++++++++++++----- SwingTwist.h | 2 ++ test/SwingTwistSingle_test.cc | 28 ++++++++++++++++++++++ 6 files changed, 90 insertions(+), 18 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 7788047..4ad5113 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -208,12 +208,32 @@ AngleOf AngleOf::operator+(const AngleOf& a) const { return angle; } +template <> +AngleOf AngleOf::operator+=(const AngleOf& a) { + this->value += a.value; + this->Normalize(); + return *this; +} + template AngleOf AngleOf::operator+=(const AngleOf& a) { this->value += a.value; return *this; } +template +void AngleOf::Normalize() { + float angleValue = this->InDegrees(); + if (!isfinite(angleValue)) + return; + + while (angleValue <= -180) + angleValue += 360; + while (angleValue > 180) + angleValue -= 360; + *this = AngleOf::Degrees(angleValue); +} + template AngleOf AngleOf::Normalize(AngleOf angle) { float angleValue = angle.InDegrees(); diff --git a/Angle.h b/Angle.h index 90531ab..69e564b 100644 --- a/Angle.h +++ b/Angle.h @@ -51,6 +51,7 @@ class AngleOf { return AngleOf::Degrees((float)f * a.InDegrees()); } + void Normalize(); static AngleOf Normalize(AngleOf a); static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); // static AngleOf Difference(AngleOf a, AngleOf b) { diff --git a/Direction.cpp b/Direction.cpp index 882ea32..c465b4a 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -22,18 +22,6 @@ DirectionOf::DirectionOf(AngleOf horizontal, AngleOf vertical) { Normalize(); }; -// template -// DirectionOf::DirectionOf(Vector3 v) { -// this->horizontal = AngleOf::Atan2( -// v.Right(), -// v.Forward()); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); -// this->vertical = -// -AngleOf::deg90 - -// AngleOf::Acos( -// v.Up()); // AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); -// Normalize(); -// } - template const DirectionOf DirectionOf::forward = DirectionOf(AngleOf(), AngleOf()); diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 459efee..1a24600 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -12,6 +12,16 @@ SwingTwistOf::SwingTwistOf() { template SwingTwistOf::SwingTwistOf(DirectionOf swing, AngleOf twist) { + // Normalize angles + AngleOf deg90 = AngleOf::Degrees(90); + AngleOf deg180 = AngleOf::Degrees(180); + + if (swing.vertical > deg90 || swing.vertical < -deg90) { + swing.horizontal += deg180; + swing.vertical = deg180 - swing.vertical; + twist += deg180; + } + this->swing = swing; this->twist = twist; } @@ -20,8 +30,16 @@ template SwingTwistOf::SwingTwistOf(AngleOf horizontal, AngleOf vertical, AngleOf twist) { - // this->horizontal = horizontal; - // this->vertical = vertical; + // Normalize angles + AngleOf deg90 = AngleOf::Degrees(90); + AngleOf deg180 = AngleOf::Degrees(180); + + if (vertical > deg90 || vertical < -deg90) { + horizontal += deg180; + vertical = deg180 - vertical; + twist += deg180; + } + this->swing = DirectionOf(horizontal, vertical); this->twist = twist; } @@ -30,9 +48,12 @@ template SwingTwistOf SwingTwistOf::Degrees(float horizontal, float vertical, float twist) { - DirectionOf swing = DirectionOf::Degrees(horizontal, vertical); - AngleOf twistAngle = AngleOf::Degrees(twist); - SwingTwistOf orientation = SwingTwistOf(swing, twistAngle); + SwingTwistOf orientation = SwingTwistOf(AngleOf::Degrees(horizontal), + AngleOf::Degrees(vertical), + AngleOf::Degrees(twist)); + // DirectionOf swing = DirectionOf::Degrees(horizontal, vertical); + // AngleOf twistAngle = AngleOf::Degrees(twist); + // SwingTwistOf orientation = SwingTwistOf(swing, twistAngle); return orientation; } @@ -49,7 +70,7 @@ SwingTwistOf SwingTwistOf::FromQuaternion(Quaternion q) { Vector3 angles = Quaternion::ToAngles(q); SwingTwistOf r = SwingTwistOf::Degrees(angles.Up(), angles.Right(), angles.Forward()); - + r.Normalize(); return r; } @@ -131,5 +152,17 @@ AngleOf SwingTwistOf::Angle(const SwingTwistOf& r1, return AngleOf::Degrees(angle); } +template +void SwingTwistOf::Normalize() { + AngleOf deg90 = AngleOf::Degrees(90); + AngleOf deg180 = AngleOf::Degrees(180); + + if (this->swing.vertical > deg90 || this->swing.vertical < -deg90) { + this->swing.horizontal += deg180; + this->swing.vertical = deg180 - this->swing.vertical; + this->twist += deg180; + } +} + template class SwingTwistOf; template class SwingTwistOf; \ No newline at end of file diff --git a/SwingTwist.h b/SwingTwist.h index 0558bbb..7fac16a 100644 --- a/SwingTwist.h +++ b/SwingTwist.h @@ -64,6 +64,8 @@ class SwingTwistOf { static SwingTwistOf AngleAxis(float angle, const DirectionOf& axis); static AngleOf Angle(const SwingTwistOf& r1, const SwingTwistOf& r2); + + void Normalize(); }; using SwingTwistSingle = SwingTwistOf; diff --git a/test/SwingTwistSingle_test.cc b/test/SwingTwistSingle_test.cc index 14f4b81..8885ae4 100644 --- a/test/SwingTwistSingle_test.cc +++ b/test/SwingTwistSingle_test.cc @@ -100,4 +100,32 @@ TEST(SwingTwistSingle, AngleAxis) { << "270 up"; } +TEST(SwingTwistSingle, Normalize) { + SwingTwistSingle s; + + s = SwingTwistSingle::Degrees(0, 0, 0); + EXPECT_EQ(s, SwingTwistSingle::Degrees(0, 0, 0)) << "0 0 0 Normalized"; + + s = SwingTwistSingle::Degrees(0, 180, 0); + EXPECT_EQ(s, SwingTwistSingle::Degrees(180, 0, 180)) << "0 180 0 Normalized"; + + s = SwingTwistSingle::Degrees(0, 180, 180); + EXPECT_EQ(s, SwingTwistSingle::Degrees(180, 0, 0)) << "0 180 180 Normalized"; + + s = SwingTwistSingle::Degrees(270, 90, 0); + EXPECT_EQ(s, SwingTwistSingle::Degrees(-90, 90, 0)) << "270 90 0 Normalized"; + + s = SwingTwistSingle::Degrees(270, 270, 0); + EXPECT_EQ(s, SwingTwistSingle::Degrees(-90, -90, 0)) + << "270 270 0 Normalized"; + + s = SwingTwistSingle::Degrees(270, 225, 0); + EXPECT_EQ(s, SwingTwistSingle::Degrees(90, -45, -180)) + << "270 225 0 Normalized"; + + s = SwingTwistSingle::Degrees(270, 0, 225); + EXPECT_EQ(s, SwingTwistSingle::Degrees(-90, 0, -135)) + << "270 0 225 Normalized"; +} + #endif \ No newline at end of file From 18756ba1a5fea48d0678737f6f878570e73fec61 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 27 Sep 2024 15:48:35 +0200 Subject: [PATCH 107/121] Correct axis on quaternion from swingtwist --- SwingTwist.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SwingTwist.cpp b/SwingTwist.cpp index 1a24600..58905c7 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -49,7 +49,7 @@ SwingTwistOf SwingTwistOf::Degrees(float horizontal, float vertical, float twist) { SwingTwistOf orientation = SwingTwistOf(AngleOf::Degrees(horizontal), - AngleOf::Degrees(vertical), + -AngleOf::Degrees(vertical), AngleOf::Degrees(twist)); // DirectionOf swing = DirectionOf::Degrees(horizontal, vertical); // AngleOf twistAngle = AngleOf::Degrees(twist); @@ -59,7 +59,7 @@ SwingTwistOf SwingTwistOf::Degrees(float horizontal, template Quaternion SwingTwistOf::ToQuaternion() const { - Quaternion q = Quaternion::Euler(this->swing.vertical.InDegrees(), + Quaternion q = Quaternion::Euler(-this->swing.vertical.InDegrees(), this->swing.horizontal.InDegrees(), this->twist.InDegrees()); return q; From 536d6cef19a0b50b9ef6d5e2ba119c0d3f24a26b Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 29 Nov 2024 12:56:46 +0100 Subject: [PATCH 108/121] Add Binary support --- Angle.cpp | 113 +++++++++++++++++++++--------------------------------- Angle.h | 26 ++++++------- 2 files changed, 56 insertions(+), 83 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 4ad5113..7bf8bc2 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -3,8 +3,8 @@ // file, You can obtain one at https ://mozilla.org/MPL/2.0/. #include "Angle.h" -#include #include "FloatSingle.h" +#include const float Rad2Deg = 57.29578F; const float Deg2Rad = 0.0174532924F; @@ -23,16 +23,13 @@ float Angle::Normalize(float angle) { //---------------------- -template -AngleOf::AngleOf() : value(0) {} +template AngleOf::AngleOf() : value(0) {} -template -AngleOf::AngleOf(T angle) : value(angle) {} +template AngleOf::AngleOf(T angle) : value(angle) {} //===== AngleSingle, AngleOf -template <> -AngleOf AngleOf::Degrees(float angle) { +template <> AngleOf AngleOf::Degrees(float angle) { if (isfinite(angle)) { while (angle < -180) angle += 360; @@ -43,8 +40,7 @@ AngleOf AngleOf::Degrees(float angle) { return AngleOf(angle); } -template <> -AngleOf AngleOf::Radians(float angle) { +template <> AngleOf AngleOf::Radians(float angle) { if (isfinite(angle)) { while (angle <= -pi) angle += 2 * pi; @@ -55,27 +51,27 @@ AngleOf AngleOf::Radians(float angle) { return AngleOf(angle * Rad2Deg); } -template <> -float AngleOf::InDegrees() const { - return this->value; +template AngleOf AngleOf::Binary(T x) { + AngleOf angle = AngleOf(); + angle.value = x; + return angle; } -template <> -float AngleOf::InRadians() const { +template <> float AngleOf::InDegrees() const { return this->value; } + +template <> float AngleOf::InRadians() const { return this->value * Deg2Rad; } //===== Angle16, AngleOf -template <> -AngleOf AngleOf::Degrees(float angle) { +template <> AngleOf AngleOf::Degrees(float angle) { // map float [-180..180) to integer [-32768..32767] signed short value = (signed short)(angle / 360.0F * 65536.0F); return AngleOf(value); } -template <> -AngleOf AngleOf::Radians(float angle) { +template <> AngleOf AngleOf::Radians(float angle) { if (!isfinite(angle)) return AngleOf(0); @@ -84,29 +80,25 @@ AngleOf AngleOf::Radians(float angle) { return AngleOf(value); } -template <> -float AngleOf::InDegrees() const { +template <> float AngleOf::InDegrees() const { float degrees = this->value / 65536.0f * 360.0f; return degrees; } -template <> -float AngleOf::InRadians() const { +template <> float AngleOf::InRadians() const { float radians = this->value / 65536.0f * (2 * pi); return radians; } //===== Angle8, AngleOf -template <> -AngleOf AngleOf::Degrees(float angle) { +template <> AngleOf AngleOf::Degrees(float angle) { // map float [-180..180) to integer [-128..127) signed char value = (signed char)(angle / 360.0F * 256.0F); return AngleOf(value); } -template <> -AngleOf AngleOf::Radians(float angle) { +template <> AngleOf AngleOf::Radians(float angle) { if (!isfinite(angle)) return AngleOf(0); @@ -115,14 +107,12 @@ AngleOf AngleOf::Radians(float angle) { return AngleOf(value); } -template <> -float AngleOf::InDegrees() const { +template <> float AngleOf::InDegrees() const { float degrees = this->value / 256.0f * 360.0f; return degrees; } -template <> -float AngleOf::InRadians() const { +template <> float AngleOf::InRadians() const { float radians = this->value / 128.0f * pi; return radians; } @@ -136,28 +126,23 @@ float AngleOf::InRadians() const { // template // const AngleOf AngleOf::deg180 = AngleOf::Degrees(180); -template -bool AngleOf::operator==(const AngleOf a) const { +template bool AngleOf::operator==(const AngleOf a) const { return this->value == a.value; } -template -bool AngleOf::operator>(AngleOf a) const { +template bool AngleOf::operator>(AngleOf a) const { return this->value > a.value; } -template -bool AngleOf::operator>=(AngleOf a) const { +template bool AngleOf::operator>=(AngleOf a) const { return this->value >= a.value; } -template -bool AngleOf::operator<(AngleOf a) const { +template bool AngleOf::operator<(AngleOf a) const { return this->value < a.value; } -template -bool AngleOf::operator<=(AngleOf a) const { +template bool AngleOf::operator<=(AngleOf a) const { return this->value <= a.value; } @@ -178,51 +163,47 @@ AngleOf Passer::LinearAlgebra::AngleOf::Abs(AngleOf a) { return a; } -template -AngleOf AngleOf::operator-() const { +template AngleOf AngleOf::operator-() const { AngleOf angle = AngleOf(-this->value); return angle; } template <> -AngleOf AngleOf::operator-(const AngleOf& a) const { +AngleOf AngleOf::operator-(const AngleOf &a) const { AngleOf angle = AngleOf(this->value - a.value); angle = Normalize(angle); return angle; } template -AngleOf AngleOf::operator-(const AngleOf& a) const { +AngleOf AngleOf::operator-(const AngleOf &a) const { AngleOf angle = AngleOf(this->value - a.value); return angle; } template <> -AngleOf AngleOf::operator+(const AngleOf& a) const { +AngleOf AngleOf::operator+(const AngleOf &a) const { AngleOf angle = AngleOf(this->value + a.value); angle = Normalize(angle); return angle; } template -AngleOf AngleOf::operator+(const AngleOf& a) const { +AngleOf AngleOf::operator+(const AngleOf &a) const { AngleOf angle = AngleOf(this->value + a.value); return angle; } -template <> -AngleOf AngleOf::operator+=(const AngleOf& a) { +template <> AngleOf AngleOf::operator+=(const AngleOf &a) { this->value += a.value; this->Normalize(); return *this; } -template -AngleOf AngleOf::operator+=(const AngleOf& a) { +template AngleOf AngleOf::operator+=(const AngleOf &a) { this->value += a.value; return *this; } -template -void AngleOf::Normalize() { +template void AngleOf::Normalize() { float angleValue = this->InDegrees(); if (!isfinite(angleValue)) return; @@ -234,8 +215,7 @@ void AngleOf::Normalize() { *this = AngleOf::Degrees(angleValue); } -template -AngleOf AngleOf::Normalize(AngleOf angle) { +template AngleOf AngleOf::Normalize(AngleOf angle) { float angleValue = angle.InDegrees(); if (!isfinite(angleValue)) return angle; @@ -254,10 +234,9 @@ AngleOf AngleOf::Clamp(AngleOf angle, AngleOf min, AngleOf max) { } template -AngleOf AngleOf::MoveTowards(AngleOf fromAngle, - AngleOf toAngle, +AngleOf AngleOf::MoveTowards(AngleOf fromAngle, AngleOf toAngle, float maxDegrees) { - maxDegrees = fmaxf(0, maxDegrees); // filter out negative distances + maxDegrees = fmaxf(0, maxDegrees); // filter out negative distances AngleOf d = toAngle - fromAngle; float dDegrees = Abs(d).InDegrees(); d = AngleOf::Degrees(Float::Clamp(dDegrees, 0, maxDegrees)); @@ -267,29 +246,23 @@ AngleOf AngleOf::MoveTowards(AngleOf fromAngle, return fromAngle + d; } -template -float AngleOf::Cos(AngleOf a) { +template float AngleOf::Cos(AngleOf a) { return cosf(a.InRadians()); } -template -float AngleOf::Sin(AngleOf a) { +template float AngleOf::Sin(AngleOf a) { return sinf(a.InRadians()); } -template -float AngleOf::Tan(AngleOf a) { +template float AngleOf::Tan(AngleOf a) { return tanf(a.InRadians()); } -template -AngleOf AngleOf::Acos(float f) { +template AngleOf AngleOf::Acos(float f) { return AngleOf::Radians(acosf(f)); } -template -AngleOf AngleOf::Asin(float f) { +template AngleOf AngleOf::Asin(float f) { return AngleOf::Radians(asinf(f)); } -template -AngleOf AngleOf::Atan(float f) { +template AngleOf AngleOf::Atan(float f) { return AngleOf::Radians(atanf(f)); } @@ -321,7 +294,7 @@ float AngleOf::CosineRuleSide(float a, float b, AngleOf gamma) { float b2 = b * b; float d = a2 + b2 - - 2 * a * b * Cos(gamma); // cosf(gamma * Passer::LinearAlgebra::Deg2Rad); + 2 * a * b * Cos(gamma); // cosf(gamma * Passer::LinearAlgebra::Deg2Rad); // Catch edge cases where float inacuracies lead tot nans if (d < 0) return 0; diff --git a/Angle.h b/Angle.h index 69e564b..89ae2fe 100644 --- a/Angle.h +++ b/Angle.h @@ -13,13 +13,13 @@ static float pi = 3.1415927410125732421875F; static float Rad2Deg = 360.0f / (pi * 2); static float Deg2Rad = (pi * 2) / 360.0f; -template -class AngleOf { - public: +template class AngleOf { +public: AngleOf(); static AngleOf Degrees(float f); static AngleOf Radians(float f); + static AngleOf Binary(T x); // const static AngleOf zero; // const static AngleOf deg90; @@ -29,6 +29,7 @@ class AngleOf { float InRadians() const; inline T GetBinary() const { return this->value; } + inline void SetBinary(T x) { this->value = x; } bool operator==(const AngleOf a) const; bool operator>(AngleOf a) const; @@ -40,14 +41,14 @@ class AngleOf { static AngleOf Abs(AngleOf a); AngleOf operator-() const; - AngleOf operator-(const AngleOf& a) const; - AngleOf operator+(const AngleOf& a) const; - AngleOf operator+=(const AngleOf& a); + AngleOf operator-(const AngleOf &a) const; + AngleOf operator+(const AngleOf &a) const; + AngleOf operator+=(const AngleOf &a); - friend AngleOf operator*(const AngleOf& a, float f) { + friend AngleOf operator*(const AngleOf &a, float f) { return AngleOf::Degrees((float)a.InDegrees() * f); } - friend AngleOf operator*(float f, const AngleOf& a) { + friend AngleOf operator*(float f, const AngleOf &a) { return AngleOf::Degrees((float)f * a.InDegrees()); } @@ -58,8 +59,7 @@ class AngleOf { // AngleOf r = Normalize(b.InDegrees() - a.InDegrees()); // return r; // }; - static AngleOf MoveTowards(AngleOf fromAngle, - AngleOf toAngle, + static AngleOf MoveTowards(AngleOf fromAngle, AngleOf toAngle, float maxAngle); static float Cos(AngleOf a); @@ -76,7 +76,7 @@ class AngleOf { static AngleOf SineRuleAngle(float a, AngleOf beta, float c); - private: +private: T value; AngleOf(T value); @@ -91,8 +91,8 @@ using AngleSingle = AngleOf; using Angle16 = AngleOf; using Angle8 = AngleOf; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #endif \ No newline at end of file From 800eb75e28eb68a306f6b6857026f81653735efc Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sat, 14 Dec 2024 12:40:25 +0100 Subject: [PATCH 109/121] improved rounding of discrete angles --- Angle.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 7bf8bc2..3c02710 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -67,7 +67,7 @@ template <> float AngleOf::InRadians() const { template <> AngleOf AngleOf::Degrees(float angle) { // map float [-180..180) to integer [-32768..32767] - signed short value = (signed short)(angle / 360.0F * 65536.0F); + signed short value = (signed short)roundf(angle / 360.0F * 65536.0F); return AngleOf(value); } @@ -76,7 +76,7 @@ template <> AngleOf AngleOf::Radians(float angle) { return AngleOf(0); // map float [-PI..PI) to integer [-32768..32767] - signed short value = (signed short)(angle / pi * 32768.0F); + signed short value = (signed short)roundf(angle / pi * 32768.0F); return AngleOf(value); } @@ -94,7 +94,7 @@ template <> float AngleOf::InRadians() const { template <> AngleOf AngleOf::Degrees(float angle) { // map float [-180..180) to integer [-128..127) - signed char value = (signed char)(angle / 360.0F * 256.0F); + signed char value = (signed char)roundf(angle / 360.0F * 256.0F); return AngleOf(value); } @@ -103,7 +103,7 @@ template <> AngleOf AngleOf::Radians(float angle) { return AngleOf(0); // map float [-pi..pi) to integer [-128..127) - signed char value = (signed char)(angle / pi * 128.0f); + signed char value = (signed char)roundf(angle / pi * 128.0f); return AngleOf(value); } From 28ee2254b89167641322ab0efb753fe2670efa8a Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 18 Dec 2024 16:54:33 +0100 Subject: [PATCH 110/121] Normalize Spherical at creation --- Spherical.cpp | 95 ++++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 61 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index a88f704..55836a9 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -5,55 +5,34 @@ #include -template -SphericalOf::SphericalOf() { +template SphericalOf::SphericalOf() { this->distance = 0.0f; this->direction = DirectionOf(); - // this->horizontal = AngleOf(); - // this->vertical = AngleOf(); } -// template <> -// SphericalOf::SphericalOf() { -// this->distance = 0.0f; -// this->horizontal = AngleOf(0); -// this->vertical = AngleOf(0); -// } - template -SphericalOf::SphericalOf(float distance, - AngleOf horizontal, +SphericalOf::SphericalOf(float distance, AngleOf horizontal, AngleOf vertical) { - this->distance = distance; - this->direction = DirectionOf(horizontal, vertical); - // this->horizontal = horizontal; - // this->vertical = vertical; + if (distance < 0) { + this->distance = distance; + this->direction = DirectionOf(horizontal, vertical); + } else { + this->distance = -distance; + this->direction = -DirectionOf(horizontal, vertical); + } } template SphericalOf::SphericalOf(float distance, DirectionOf direction) { - this->distance = distance; - this->direction = direction; + if (distance < 0) { + this->distance = -distance; + this->direction = -direction; + } else { + this->distance = distance; + this->direction = direction; + } } -// template <> -// SphericalOf::SphericalOf(float distance, -// AngleOf horizontal, -// AngleOf vertical) { -// this->distance = distance; -// this->horizontal = horizontal; -// this->vertical = vertical; -// } - -// template <> -// SphericalOf::SphericalOf(float distance, -// AngleOf horizontal, -// AngleOf vertical) { -// this->distance = distance; -// this->horizontal = horizontal; -// this->vertical = vertical; -// } - template SphericalOf SphericalOf::FromPolar(PolarOf polar) { AngleOf horizontal = polar.angle; @@ -62,8 +41,7 @@ SphericalOf SphericalOf::FromPolar(PolarOf polar) { return r; } -template -SphericalOf SphericalOf::FromVector3(Vector3 v) { +template SphericalOf SphericalOf::FromVector3(Vector3 v) { float distance = v.magnitude(); if (distance == 0.0f) { return SphericalOf(distance, AngleOf(), AngleOf()); @@ -76,8 +54,7 @@ SphericalOf SphericalOf::FromVector3(Vector3 v) { } } -template -Vector3 SphericalOf::ToVector3() const { +template Vector3 SphericalOf::ToVector3() const { float verticalRad = (pi / 2) - this->direction.vertical.InRadians(); float horizontalRad = this->direction.horizontal.InRadians(); @@ -122,8 +99,7 @@ SphericalOf SphericalOf::WithDistance(float distance) { return SphericalOf(); } -template -SphericalOf SphericalOf::operator-() const { +template SphericalOf SphericalOf::operator-() const { SphericalOf v = SphericalOf( this->distance, this->direction.horizontal + AngleOf::Degrees(180), this->direction.vertical + AngleOf::Degrees(180)); @@ -131,7 +107,7 @@ SphericalOf SphericalOf::operator-() const { } template -SphericalOf SphericalOf::operator-(const SphericalOf& s2) const { +SphericalOf SphericalOf::operator-(const SphericalOf &s2) const { // let's do it the easy way... Vector3 v1 = this->ToVector3(); Vector3 v2 = s2.ToVector3(); @@ -140,13 +116,13 @@ SphericalOf SphericalOf::operator-(const SphericalOf& s2) const { return r; } template -SphericalOf SphericalOf::operator-=(const SphericalOf& v) { +SphericalOf SphericalOf::operator-=(const SphericalOf &v) { *this = *this - v; return *this; } template -SphericalOf SphericalOf::operator+(const SphericalOf& s2) const { +SphericalOf SphericalOf::operator+(const SphericalOf &s2) const { // let's do it the easy way... Vector3 v1 = this->ToVector3(); Vector3 v2 = s2.ToVector3(); @@ -201,19 +177,17 @@ SphericalOf SphericalOf::operator+(const SphericalOf& s2) const { */ } template -SphericalOf SphericalOf::operator+=(const SphericalOf& v) { +SphericalOf SphericalOf::operator+=(const SphericalOf &v) { *this = *this + v; return *this; } -template -SphericalOf SphericalOf::operator*=(float f) { +template SphericalOf SphericalOf::operator*=(float f) { this->distance *= f; return *this; } -template -SphericalOf SphericalOf::operator/=(float f) { +template SphericalOf SphericalOf::operator/=(float f) { this->distance /= f; return *this; } @@ -224,8 +198,8 @@ SphericalOf SphericalOf::operator/=(float f) { const float epsilon = 1E-05f; template -float SphericalOf::DistanceBetween(const SphericalOf& v1, - const SphericalOf& v2) { +float SphericalOf::DistanceBetween(const SphericalOf &v1, + const SphericalOf &v2) { // SphericalOf difference = v1 - v2; // return difference.distance; Vector3 vec1 = v1.ToVector3(); @@ -235,8 +209,8 @@ float SphericalOf::DistanceBetween(const SphericalOf& v1, } template -AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, - const SphericalOf& v2) { +AngleOf SphericalOf::AngleBetween(const SphericalOf &v1, + const SphericalOf &v2) { // float denominator = v1.distance * v2.distance; // if (denominator < epsilon) // return 0.0f; @@ -256,9 +230,8 @@ AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, template AngleOf Passer::LinearAlgebra::SphericalOf::SignedAngleBetween( - const SphericalOf& v1, - const SphericalOf& v2, - const SphericalOf& axis) { + const SphericalOf &v1, const SphericalOf &v2, + const SphericalOf &axis) { Vector3 v1_vector = v1.ToVector3(); Vector3 v2_vector = v2.ToVector3(); Vector3 axis_vector = axis.ToVector3(); @@ -267,7 +240,7 @@ AngleOf Passer::LinearAlgebra::SphericalOf::SignedAngleBetween( } template -SphericalOf SphericalOf::Rotate(const SphericalOf& v, +SphericalOf SphericalOf::Rotate(const SphericalOf &v, AngleOf horizontalAngle, AngleOf verticalAngle) { SphericalOf r = @@ -276,14 +249,14 @@ SphericalOf SphericalOf::Rotate(const SphericalOf& v, return r; } template -SphericalOf SphericalOf::RotateHorizontal(const SphericalOf& v, +SphericalOf SphericalOf::RotateHorizontal(const SphericalOf &v, AngleOf a) { SphericalOf r = SphericalOf(v.distance, v.direction.horizontal + a, v.direction.vertical); return r; } template -SphericalOf SphericalOf::RotateVertical(const SphericalOf& v, +SphericalOf SphericalOf::RotateVertical(const SphericalOf &v, AngleOf a) { SphericalOf r = SphericalOf(v.distance, v.direction.horizontal, v.direction.vertical + a); From 2c57c3f6c07537a3d5f066dc970f5472f68c586b Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 18 Dec 2024 16:58:57 +0100 Subject: [PATCH 111/121] Fixed direction for spherical --- Spherical.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index 55836a9..671b04c 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -14,11 +14,11 @@ template SphericalOf::SphericalOf(float distance, AngleOf horizontal, AngleOf vertical) { if (distance < 0) { - this->distance = distance; - this->direction = DirectionOf(horizontal, vertical); - } else { this->distance = -distance; this->direction = -DirectionOf(horizontal, vertical); + } else { + this->distance = distance; + this->direction = DirectionOf(horizontal, vertical); } } From a7aa679494a28e6a9f527ee39ad073efcb118ccf Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Dec 2024 10:03:47 +0100 Subject: [PATCH 112/121] Added a performance test --- test/Polar_test.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/test/Polar_test.cc b/test/Polar_test.cc index a470593..0586108 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Polar.h" #include "Spherical.h" @@ -173,4 +173,59 @@ TEST(Polar, Rotate) { EXPECT_FLOAT_EQ(r.angle.InDegrees(), 90.0f) << "Rotate(4 45, 45)"; } +// Performance Test +TEST(PolarOfTest, PerformanceTest) { + const int numIterations = 1000000; // Number of instances to test + std::vector> polarObjects; + + // Measure time for creating a large number of PolarOf objects + auto start = std::chrono::high_resolution_clock::now(); + + for (int i = 0; i < numIterations; ++i) { + float distance = + static_cast(rand() % 100); // Random distance from 0 to 100 + AngleOf angle = AngleOf::Degrees( + static_cast(rand() % 360)); // Random angle from 0 to 360 degrees + PolarOf p = PolarOf(distance, angle); + polarObjects.emplace_back(p); // Create and store the object + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Time to construct " << numIterations + << " PolarOf objects: " << duration.count() << " seconds." + << std::endl; + + // Test completion with a message + ASSERT_GE(duration.count(), 0); // Ensure duration is non-negative + + // Assert that the duration is less than or equal to 1 second + ASSERT_LE(duration.count(), 1.0) + << "Performance test failed: Construction took longer than 1 second."; +} + +// Edge Case 1: Testing with distance = 0 and angle = 45 +TEST(PolarOfTest, TestDistanceZero) { + PolarOf p1(0.0f, AngleOf::Degrees(45.0f)); + EXPECT_EQ(p1.distance, 0.0f); // Ensure distance is 0 + EXPECT_EQ(p1.angle.InDegrees(), 0.0f); // Ensure angle is 0 when distance is 0 +} + +// Edge Case 2: Testing with negative distance, angle should be adjusted +// TEST(PolarOfTest, TestNegativeDistance) { +// PolarOf p2(-10.0f, AngleOf::Degrees(90.0f)); +// EXPECT_EQ(p2.distance, 10.0f); // Ensure distance is positive +// EXPECT_NEAR(p2.angle.InDegrees(), 270.0f, +// 0.0001f); // Ensure angle is normalized to 270 degrees (180 + +// 90) +// } + +// Edge Case 3: Testing with positive distance and angle = 180 +// TEST(PolarOfTest, TestPositiveDistance) { +// PolarOf p3(100.0f, AngleOf::Degrees(180.0f)); +// EXPECT_EQ(p3.distance, 100.0f); // Ensure distance is correct +// EXPECT_NEAR(p3.angle.InDegrees(), 180.0f, 0.0001f); // Ensure angle is +// correct +// } + #endif \ No newline at end of file From d3226fddc920c12f32c6ed94ade3e8d42438e03d Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Dec 2024 10:55:42 +0100 Subject: [PATCH 113/121] Added copilot test documentation --- Spherical.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Spherical.cpp b/Spherical.cpp index 671b04c..dbbba17 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -54,6 +54,17 @@ template SphericalOf SphericalOf::FromVector3(Vector3 v) { } } +/** + * @brief Converts spherical coordinates to a 3D vector. + * + * This function converts the spherical coordinates represented by the + * SphericalOf object to a 3D vector (Vector3). The conversion is based + * on the distance and direction (vertical and horizontal angles) of the + * spherical coordinates. + * + * @tparam T The type of the distance and direction values. + * @return Vector3 The 3D vector representation of the spherical coordinates. + */ template Vector3 SphericalOf::ToVector3() const { float verticalRad = (pi / 2) - this->direction.vertical.InRadians(); float horizontalRad = this->direction.horizontal.InRadians(); From 585a3b0fe590ca740b7303a7f83108788d40c640 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Dec 2024 11:02:35 +0100 Subject: [PATCH 114/121] Removed default Spherical type --- Spherical.cpp | 225 ------------------------------------------- Spherical.h | 191 +++++------------------------------- Vector3.cpp | 49 +++++----- test/Vector3_test.cc | 8 +- 4 files changed, 49 insertions(+), 424 deletions(-) diff --git a/Spherical.cpp b/Spherical.cpp index dbbba17..2b841f3 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -276,228 +276,3 @@ SphericalOf SphericalOf::RotateVertical(const SphericalOf &v, template class SphericalOf; template class SphericalOf; - -//--------------------------------------- -/* -Spherical::Spherical() { - this->distance = 0.0f; - this->horizontalAngle = 0.0f; - this->verticalAngle = 0.0f; -} - -// Spherical::Spherical(Polar polar) { -// this->distance = polar.distance; -// this->horizontalAngle = polar.angle; -// this->verticalAngle = 0.0f; -// } - -Spherical::Spherical(float distance, - Angle horizontalAngle, - Angle verticalAngle) { - if (distance < 0) { - this->distance = -distance; - this->horizontalAngle = - Angle::Normalize(horizontalAngle.ToFloat() - 180.0f); - this->verticalAngle = verticalAngle; - } else { - this->distance = distance; - this->horizontalAngle = Angle::Normalize(horizontalAngle); - this->verticalAngle = Angle::Normalize(verticalAngle); - } -} - -Spherical::Spherical(Vector3 v) { - this->distance = v.magnitude(); - if (distance == 0.0f) { - this->verticalAngle = 0.0f; - this->horizontalAngle = 0.0f; - } else { - this->verticalAngle = (90.0f - acosf(v.Up() / this->distance) * - Passer::LinearAlgebra::Rad2Deg); - this->horizontalAngle = - atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; - } -} - -const Spherical Spherical::zero = Spherical(0.0f, 0.0f, 0.0f); -const Spherical Spherical::forward = Spherical(1.0f, 0.0f, 0.0f); -const Spherical Spherical::back = Spherical(1.0f, 180.0f, 0.0f); -const Spherical Spherical::right = Spherical(1.0f, 90.0f, 0.0f); -const Spherical Spherical::left = Spherical(1.0f, -90.0f, 0.0f); -const Spherical Spherical::up = Spherical(1.0f, 0.0f, 90.0f); -const Spherical Spherical::down = Spherical(1.0f, 0.0f, -90.0f); - -bool Spherical::operator==(const Spherical& v) const { - return (this->distance == v.distance && - this->horizontalAngle.ToFloat() == v.horizontalAngle.ToFloat() && - this->verticalAngle.ToFloat() == v.verticalAngle.ToFloat()); -} - -Spherical Spherical::Normalize(const Spherical& v) { - Spherical r = Spherical(1, v.horizontalAngle, v.verticalAngle); - return r; -} -Spherical Spherical::normalized() const { - Spherical r = Spherical(1, this->horizontalAngle, this->verticalAngle); - return r; -} - -Spherical Spherical::operator-() const { - Spherical v = - Spherical(this->distance, this->horizontalAngle.ToFloat() + 180.0f, - this->verticalAngle.ToFloat() + 180.0f); - return v; -} - -Spherical Spherical::operator-(const Spherical& s2) const { - // let's do it the easy way... - Vector3 v1 = Vector3(*this); - Vector3 v2 = Vector3(s2); - Vector3 v = v1 - v2; - Spherical r = Spherical(v); - return r; -} -Spherical Spherical::operator-=(const Spherical& v) { - *this = *this - v; - return *this; -} - -Spherical Spherical::operator+(const Spherical& s2) const { - // let's do it the easy way... - Vector3 v1 = Vector3(*this); - Vector3 v2 = Vector3(s2); - Vector3 v = v1 + v2; - Spherical r = Spherical(v); - return r; - - // This is the hard way... - // if (v2.distance <= 0) - // return Spherical(this->distance, this->horizontalAngle, - // this->verticalAngle); - // if (this->distance <= 0) - // return v2; - - // float deltaHorizontalAngle = - // (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); - // float horizontalRotation = deltaHorizontalAngle < 0 - // ? 180 + deltaHorizontalAngle - // : 180 - deltaHorizontalAngle; - // float deltaVerticalAngle = - // Angle::Normalize(v2.verticalAngle - this->verticalAngle); - // float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle - // : 180 - deltaVerticalAngle; - - // if (horizontalRotation == 180 && verticalRotation == 180) - // // angle is too small, take this angle and add the distances - // return Spherical(this->distance + v2.distance, this->horizontalAngle, - // this->verticalAngle); - - // Angle rotation = AngleBetween(*this, v2); - // float newDistance = - // Angle::CosineRuleSide(v2.distance, this->distance, rotation); - // float angle = - // Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); - - // // Now we have to project the angle to the horizontal and vertical -planes... - // // The axis for the angle is the cross product of the two spherical vectors - // // (which function we do not have either...) - // float horizontalAngle = 0; - // float verticalAngle = 0; - - // float newHorizontalAngle = - // deltaHorizontalAngle < 0 - // ? Angle::Normalize(this->horizontalAngle - horizontalAngle) - // : Angle::Normalize(this->horizontalAngle + horizontalAngle); - // float newVerticalAngle = - // deltaVerticalAngle < 0 - // ? Angle::Normalize(this->verticalAngle - verticalAngle) - // : Angle::Normalize(this->verticalAngle + verticalAngle); - - // Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); - -} -Spherical Spherical::operator+=(const Spherical& v) { - *this = *this + v; - return *this; -} - -// Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { -// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); -// } -// Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) { -// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); -// } -Spherical Spherical::operator*=(float f) { - this->distance *= f; - return *this; -} - -// Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { -// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); -// } -// Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) { -// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); -// } -Spherical Spherical::operator/=(float f) { - this->distance /= f; - return *this; -} - -// float Spherical::GetSwing() { -// // Not sure if this is correct -// return sqrtf(horizontalAngle * horizontalAngle + -// verticalAngle * verticalAngle); -// } - -// float Spherical::Distance(const Spherical &s1, const Spherical &s2) { -// float d = 0; -// return d; -// } - -#include "AngleUsing.h" -#include "FloatSingle.h" -#include "Vector3.h" - -const float epsilon = 1E-05f; -const float Rad2Deg = 57.29578F; - -Angle Spherical::AngleBetween(const Spherical& v1, const Spherical& v2) { - // float denominator = sqrtf(v1_3.sqrMagnitude() * v2_3.sqrMagnitude()); - float denominator = - v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * - // v2.distance * v2.distance); - if (denominator < epsilon) - return 0.0f; - - Vector3 v1_3 = Vector3(v1); - Vector3 v2_3 = Vector3(v2); - float dot = Vector3::Dot(v1_3, v2_3); - float fraction = dot / denominator; - if (isnan(fraction)) - return fraction; // short cut to returning NaN universally - - float cdot = Float::Clamp(fraction, -1.0, 1.0); - float r = ((float)acos(cdot)) * Rad2Deg; - return r; -} - -Spherical Spherical::Rotate(const Spherical& v, - Angle horizontalAngle, - Angle verticalAngle) { - Spherical r = Spherical( - v.distance, v.horizontalAngle.ToFloat() + horizontalAngle.ToFloat(), - v.verticalAngle.ToFloat() + verticalAngle.ToFloat()); - return r; -} -Spherical Spherical::RotateHorizontal(const Spherical& v, Angle a) { - Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat() + a.ToFloat(), - v.verticalAngle.ToFloat()); - return r; -} -Spherical Spherical::RotateVertical(const Spherical& v, Angle a) { - Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat(), - v.verticalAngle.ToFloat() + a.ToFloat()); - return r; -} -*/ diff --git a/Spherical.h b/Spherical.h index 8d71891..3d21bab 100644 --- a/Spherical.h +++ b/Spherical.h @@ -11,12 +11,10 @@ namespace Passer { namespace LinearAlgebra { struct Vector3; -template -class PolarOf; +template class PolarOf; -template -class SphericalOf { - public: +template class SphericalOf { +public: /// @brief The distance in meters /// @remark The distance should never be negative float distance; @@ -63,23 +61,23 @@ class SphericalOf { /// @brief Subtract a spherical vector from this vector /// @param v The vector to subtract /// @return The result of the subtraction - SphericalOf operator-(const SphericalOf& v) const; - SphericalOf operator-=(const SphericalOf& v); + SphericalOf operator-(const SphericalOf &v) const; + SphericalOf operator-=(const SphericalOf &v); /// @brief Add a spherical vector to this vector /// @param v The vector to add /// @return The result of the addition - SphericalOf operator+(const SphericalOf& v) const; - SphericalOf operator+=(const SphericalOf& v); + SphericalOf operator+(const SphericalOf &v) const; + SphericalOf operator+=(const SphericalOf &v); /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend SphericalOf operator*(const SphericalOf& v, float f) { + friend SphericalOf operator*(const SphericalOf &v, float f) { return SphericalOf(v.distance * f, v.direction); } - friend SphericalOf operator*(float f, const SphericalOf& v) { + friend SphericalOf operator*(float f, const SphericalOf &v) { return SphericalOf(f * v.distance, v.direction); } SphericalOf operator*=(float f); @@ -88,178 +86,35 @@ class SphericalOf { /// @return The scaled factor /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend SphericalOf operator/(const SphericalOf& v, float f) { + friend SphericalOf operator/(const SphericalOf &v, float f) { return SphericalOf(v.distance / f, v.direction); } - friend SphericalOf operator/(float f, const SphericalOf& v) { + friend SphericalOf operator/(float f, const SphericalOf &v) { return SphericalOf(f / v.distance, v.direction); } SphericalOf operator/=(float f); - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vector - /// The distance between the two vectors - // static float Distance(const Spherical &s1, const Spherical &s2); + static float DistanceBetween(const SphericalOf &v1, + const SphericalOf &v2); + static AngleOf AngleBetween(const SphericalOf &v1, + const SphericalOf &v2); + static AngleOf SignedAngleBetween(const SphericalOf &v1, + const SphericalOf &v2, + const SphericalOf &axis); - static float DistanceBetween(const SphericalOf& v1, - const SphericalOf& v2); - static AngleOf AngleBetween(const SphericalOf& v1, - const SphericalOf& v2); - static AngleOf SignedAngleBetween(const SphericalOf& v1, - const SphericalOf& v2, - const SphericalOf& axis); - - static SphericalOf Rotate(const SphericalOf& v, - AngleOf horizontalAngle, + static SphericalOf Rotate(const SphericalOf &v, AngleOf horizontalAngle, AngleOf verticalAngle); - static SphericalOf RotateHorizontal(const SphericalOf& v, + static SphericalOf RotateHorizontal(const SphericalOf &v, AngleOf angle); - static SphericalOf RotateVertical(const SphericalOf& v, + static SphericalOf RotateVertical(const SphericalOf &v, AngleOf angle); }; using SphericalSingle = SphericalOf; using Spherical16 = SphericalOf; -using Spherical = SphericalSingle; -/* -/// @brief A spherical vector -/// @details This is a vector in 3D space using a spherical coordinate system. -/// It consists of a distance and the polar and elevation angles from a -/// reference direction. The reference direction is typically thought of -/// as a forward direction. -struct Spherical { - public: - /// @brief The distance in meters - /// @remark The distance should never be negative - float distance; - /// @brief The angle in the horizontal plane in degrees, clockwise rotation - /// @details The angle is automatically normalized to -180 .. 180 - Angle horizontalAngle; - /// @brief The angle in the vertical plane in degrees. Positive is upward. - /// @details The angle is automatically normalized to -180 .. 180 - Angle verticalAngle; - /// @brief Create a new spherical vector with zero degrees and distance - Spherical(); - /// @brief Create a new spherical vector - /// @param distance The distance in meters - /// @param horizontalAngle The angle in the horizontal plane in degrees, - /// clockwise rotation - /// @param verticalAngle The angle in the vertical plan in degrees, - /// zero is forward, positive is upward - Spherical(float distance, Angle horizontalAngle, Angle verticalAngle); - /// @brief Convert polar coordinates to spherical coordinates - /// @param polar The polar coordinate - // Spherical(Polar polar); - /// @brief Convert 3D carthesian coordinates to spherical coordinates - /// @param v Vector in 3D carthesian coordinates; - Spherical(Vector3 v); - - /// @brief A spherical vector with zero degree angles and distance - const static Spherical zero; - /// @brief A normalized forward-oriented vector - const static Spherical forward; - /// @brief A normalized back-oriented vector - const static Spherical back; - /// @brief A normalized right-oriented vector - const static Spherical right; - /// @brief A normalized left-oriented vector - const static Spherical left; - /// @brief A normalized up-oriented vector - const static Spherical up; - /// @brief A normalized down-oriented vector - const static Spherical down; - - /// @brief Equality test to another vector - /// @param v The vector to check against - /// @return true: if it is identical to the given vector - /// @note This uses float comparison to check equality which may have strange - /// effects. Equality on floats should be avoided. - bool operator==(const Spherical& v) const; - - /// @brief The vector length - /// @param v The vector for which you need the length - /// @return The vector length; - inline static float Magnitude(const Spherical& v) { return v.distance; } - /// @brief The vector length - /// @return The vector length - inline float magnitude() const { return this->distance; } - - /// @brief Convert the vector to a length of 1 - /// @param v The vector to convert - /// @return The vector normalized to a length of 1 - static Spherical Normalize(const Spherical& v); - /// @brief Convert the vector to a length of a - /// @return The vector normalized to a length of 1 - Spherical normalized() const; - - /// @brief Negate the vector - /// @return The negated vector - /// This will rotate the vector by 180 degrees horizontally and - /// vertically. Distance will stay the same. - Spherical operator-() const; - - /// @brief Subtract a spherical vector from this vector - /// @param v The vector to subtract - /// @return The result of the subtraction - Spherical operator-(const Spherical& v) const; - Spherical operator-=(const Spherical& v); - /// @brief Add a spherical vector to this vector - /// @param v The vector to add - /// @return The result of the addition - Spherical operator+(const Spherical& v) const; - Spherical operator+=(const Spherical& v); - - /// @brief Scale the vector uniformly up - /// @param f The scaling factor - /// @return The scaled vector - /// @remark This operation will scale the distance of the vector. The angle - /// will be unaffected. - friend Spherical operator*(const Spherical& v, float f) { - return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); - } - friend Spherical operator*(float f, const Spherical& v) { - return Spherical(v.distance * f, v.horizontalAngle, - v.verticalAngle); // not correct, should be f * v.distance - } - Spherical operator*=(float f); - /// @brief Scale the vector uniformly down - /// @param f The scaling factor - /// @return The scaled factor - /// @remark This operation will scale the distance of the vector. The angle - /// will be unaffected. - friend Spherical operator/(const Spherical& v, float f) { - return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); - } - friend Spherical operator/(float f, const Spherical& v) { - return Spherical(v.distance / f, v.horizontalAngle, - v.verticalAngle); // not correct, should be f / v.distance - } - Spherical operator/=(float f); - - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vector - /// The distance between the two vectors - // static float Distance(const Spherical &s1, const Spherical &s2); - - static Angle AngleBetween(const Spherical& v1, const Spherical& v2); - - static Spherical Rotate(const Spherical& v, - Angle horizontalAngle, - Angle verticalAngle); - static Spherical RotateHorizontal(const Spherical& v, Angle angle); - static Spherical RotateVertical(const Spherical& v, Angle angle); -}; -*/ - -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #include "Polar.h" diff --git a/Vector3.cpp b/Vector3.cpp index e3f1b8e..8a63923 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -30,7 +30,7 @@ Vector3::Vector3(Vector2 v) { this->z = v.y; } -Vector3::Vector3(Spherical s) { +Vector3::Vector3(SphericalOf s) { float verticalRad = (90.0f - s.direction.vertical.InDegrees()) * Passer::LinearAlgebra::Deg2Rad; float horizontalRad = @@ -67,21 +67,17 @@ const Vector3 Vector3::back = Vector3(0, 0, -1); // return Vector3(v.x, 0, v.y); // } -float Vector3::Magnitude(const Vector3& v) { +float Vector3::Magnitude(const Vector3 &v) { return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); } -float Vector3::magnitude() const { - return (float)sqrtf(x * x + y * y + z * z); -} +float Vector3::magnitude() const { return (float)sqrtf(x * x + y * y + z * z); } -float Vector3::SqrMagnitude(const Vector3& v) { +float Vector3::SqrMagnitude(const Vector3 &v) { return v.x * v.x + v.y * v.y + v.z * v.z; } -float Vector3::sqrMagnitude() const { - return (x * x + y * y + z * z); -} +float Vector3::sqrMagnitude() const { return (x * x + y * y + z * z); } -Vector3 Vector3::Normalize(const Vector3& v) { +Vector3 Vector3::Normalize(const Vector3 &v) { float num = Vector3::Magnitude(v); Vector3 result = Vector3::zero; if (num > epsilon) { @@ -102,26 +98,26 @@ Vector3 Vector3::operator-() const { return Vector3(-this->x, -this->y, -this->z); } -Vector3 Vector3::operator-(const Vector3& v) const { +Vector3 Vector3::operator-(const Vector3 &v) const { return Vector3(this->x - v.x, this->y - v.y, this->z - v.z); } -Vector3 Vector3::operator-=(const Vector3& v) { +Vector3 Vector3::operator-=(const Vector3 &v) { this->x -= v.x; this->y -= v.y; this->z -= v.z; return *this; } -Vector3 Vector3::operator+(const Vector3& v) const { +Vector3 Vector3::operator+(const Vector3 &v) const { return Vector3(this->x + v.x, this->y + v.y, this->z + v.z); } -Vector3 Vector3::operator+=(const Vector3& v) { +Vector3 Vector3::operator+=(const Vector3 &v) { this->x += v.x; this->y += v.y; this->z += v.z; return *this; } -Vector3 Vector3::Scale(const Vector3& v1, const Vector3& v2) { +Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) { return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } // Vector3 Passer::LinearAlgebra::operator*(const Vector3 &v, float f) { @@ -149,24 +145,24 @@ Vector3 Vector3::operator/=(float f) { return *this; } -float Vector3::Dot(const Vector3& v1, const Vector3& v2) { +float Vector3::Dot(const Vector3 &v1, const Vector3 &v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } -bool Vector3::operator==(const Vector3& v) const { +bool Vector3::operator==(const Vector3 &v) const { return (this->x == v.x && this->y == v.y && this->z == v.z); } -float Vector3::Distance(const Vector3& v1, const Vector3& v2) { +float Vector3::Distance(const Vector3 &v1, const Vector3 &v2) { return Magnitude(v1 - v2); } -Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2) { +Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) { return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } -Vector3 Vector3::Project(const Vector3& v, const Vector3& n) { +Vector3 Vector3::Project(const Vector3 &v, const Vector3 &n) { float sqrMagnitude = Dot(n, n); if (sqrMagnitude < epsilon) return Vector3::zero; @@ -177,7 +173,7 @@ Vector3 Vector3::Project(const Vector3& v, const Vector3& n) { } } -Vector3 Vector3::ProjectOnPlane(const Vector3& v, const Vector3& n) { +Vector3 Vector3::ProjectOnPlane(const Vector3 &v, const Vector3 &n) { Vector3 r = v - Project(v, n); return r; } @@ -188,7 +184,7 @@ float clamp(float x, float lower, float upper) { return upperClamp; } -AngleOf Vector3::Angle(const Vector3& v1, const Vector3& v2) { +AngleOf Vector3::Angle(const Vector3 &v1, const Vector3 &v2) { float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude()); if (denominator < epsilon) return AngleOf(); @@ -197,16 +193,15 @@ AngleOf Vector3::Angle(const Vector3& v1, const Vector3& v2) { float fraction = dot / denominator; if (isnan(fraction)) return AngleOf::Degrees( - fraction); // short cut to returning NaN universally + fraction); // short cut to returning NaN universally float cdot = clamp(fraction, -1.0, 1.0); float r = ((float)acos(cdot)); return AngleOf::Radians(r); } -AngleOf Vector3::SignedAngle(const Vector3& v1, - const Vector3& v2, - const Vector3& axis) { +AngleOf Vector3::SignedAngle(const Vector3 &v1, const Vector3 &v2, + const Vector3 &axis) { // angle in [0,180] AngleOf angle = Vector3::Angle(v1, v2); @@ -220,7 +215,7 @@ AngleOf Vector3::SignedAngle(const Vector3& v1, return AngleOf(signed_angle); } -Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) { +Vector3 Vector3::Lerp(const Vector3 &v1, const Vector3 &v2, float f) { Vector3 v = v1 + (v2 - v1) * f; return v; } diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index bd53b5a..82e57e9 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Vector3.h" @@ -9,7 +9,7 @@ TEST(Vector3, FromSpherical) { Vector3 v = Vector3(0, 0, 1); - Spherical s = Spherical::FromVector3(v); + SphericalOf s = SphericalOf::FromVector3(v); Vector3 r = Vector3(s); EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 0 1"; @@ -17,7 +17,7 @@ TEST(Vector3, FromSpherical) { EXPECT_FLOAT_EQ(r.Forward(), 1.0F) << "toVector3.z 0 0 1"; v = Vector3(0, 1, 0); - s = Spherical::FromVector3(v); + s = SphericalOf::FromVector3(v); r = Vector3(s); EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 1 0"; @@ -25,7 +25,7 @@ TEST(Vector3, FromSpherical) { EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; v = Vector3(1, 0, 0); - s = Spherical::FromVector3(v); + s = SphericalOf::FromVector3(v); r = Vector3(s); EXPECT_FLOAT_EQ(r.Right(), 1.0F) << "toVector3.x 1 0 0"; From 97d937e77cd408f8e0160e6d327bb8ce197e4e5b Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Dec 2024 11:05:49 +0100 Subject: [PATCH 115/121] Fixed (copilot) unit tests --- test/Polar_test.cc | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 0586108..8bfd55f 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -29,43 +29,43 @@ TEST(Polar, FromVector2) { } TEST(Polar, FromSpherical) { - Spherical s; + SphericalSingle s; Polar p; - s = Spherical(1, Angle::Degrees(0), Angle::Degrees(0)); + s = SphericalSingle(1, Angle::Degrees(0), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(1 0 0)"; - s = Spherical(1, Angle::Degrees(45), Angle::Degrees(0)); + s = SphericalSingle(1, Angle::Degrees(45), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 45.0F) << "p.angle FromSpherical(1 45 0)"; - s = Spherical(1, Angle::Degrees(-45), Angle::Degrees(0)); + s = SphericalSingle(1, Angle::Degrees(-45), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -45.0F) << "p.angle FromSpherical(1 -45 0)"; - s = Spherical(0, Angle::Degrees(0), Angle::Degrees(0)); + s = SphericalSingle(0, Angle::Degrees(0), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 0)"; - s = Spherical(-1, Angle::Degrees(0), Angle::Degrees(0)); + s = SphericalSingle(-1, Angle::Degrees(0), Angle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -180.0F) << "p.angle FromSpherical(-1 0 0)"; - s = Spherical(0, Angle::Degrees(0), Angle::Degrees(90)); + s = SphericalSingle(0, Angle::Degrees(0), Angle::Degrees(90)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)"; @@ -212,20 +212,19 @@ TEST(PolarOfTest, TestDistanceZero) { } // Edge Case 2: Testing with negative distance, angle should be adjusted -// TEST(PolarOfTest, TestNegativeDistance) { -// PolarOf p2(-10.0f, AngleOf::Degrees(90.0f)); -// EXPECT_EQ(p2.distance, 10.0f); // Ensure distance is positive -// EXPECT_NEAR(p2.angle.InDegrees(), 270.0f, -// 0.0001f); // Ensure angle is normalized to 270 degrees (180 + -// 90) -// } +TEST(PolarOfTest, TestNegativeDistance) { + PolarOf p2(-10.0f, AngleOf::Degrees(90.0f)); + EXPECT_EQ(p2.distance, 10.0f); // Ensure distance is positive + EXPECT_NEAR(p2.angle.InDegrees(), -90.0f, + 0.0001f); // Ensure angle is normalized to 270 degrees (180 + 90) +} // Edge Case 3: Testing with positive distance and angle = 180 -// TEST(PolarOfTest, TestPositiveDistance) { -// PolarOf p3(100.0f, AngleOf::Degrees(180.0f)); -// EXPECT_EQ(p3.distance, 100.0f); // Ensure distance is correct -// EXPECT_NEAR(p3.angle.InDegrees(), 180.0f, 0.0001f); // Ensure angle is -// correct -// } +TEST(PolarOfTest, TestPositiveDistance) { + PolarOf p3(100.0f, AngleOf::Degrees(180.0f)); + EXPECT_EQ(p3.distance, 100.0f); // Ensure distance is correct + EXPECT_NEAR(p3.angle.InDegrees(), -180.0f, + 0.0001f); // Ensure angle is correct +} #endif \ No newline at end of file From 5f58a2c69ee40fff3a523f6a253f129e38605cf9 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 26 Dec 2024 12:34:26 +0100 Subject: [PATCH 116/121] Updated documentation --- Angle.cpp | 2 +- Angle.h | 2 +- DoxyGen/DoxyWarnLogfile.txt | 534 ++++++++--------------------------- DoxyGen/Doxyfile | 9 +- README.md | 8 +- Spherical.cpp | 16 ++ Spherical.h | 65 +++++ test/Spherical16_test.cc | 39 ++- test/SphericalSingle_test.cc | 39 ++- 9 files changed, 284 insertions(+), 430 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 3c02710..6f27334 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -25,7 +25,7 @@ float Angle::Normalize(float angle) { template AngleOf::AngleOf() : value(0) {} -template AngleOf::AngleOf(T angle) : value(angle) {} +// template AngleOf::AngleOf(T angle) : value(angle) {} //===== AngleSingle, AngleOf diff --git a/Angle.h b/Angle.h index 89ae2fe..cd37350 100644 --- a/Angle.h +++ b/Angle.h @@ -53,7 +53,7 @@ public: } void Normalize(); - static AngleOf Normalize(AngleOf a); + static AngleOf Normalize(AngleOf angle); static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); // static AngleOf Difference(AngleOf a, AngleOf b) { // AngleOf r = Normalize(b.InDegrees() - a.InDegrees()); diff --git a/DoxyGen/DoxyWarnLogfile.txt b/DoxyGen/DoxyWarnLogfile.txt index d37d508..2e253db 100644 --- a/DoxyGen/DoxyWarnLogfile.txt +++ b/DoxyGen/DoxyWarnLogfile.txt @@ -1,420 +1,120 @@ -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_for_dummies.md:566: warning: multiple use of section label 'OrderedCalls' while adding section, (first occurrence: D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md, line 1674) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:411: warning: multiple use of section label 'DefaultValue' while adding section, (first occurrence: D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md, line 2088) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-message.h:62: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h:158: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-output-test_.cc:47: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest-typed-test_test.cc:43: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-matchers.h:256: warning: found documented #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ but ignoring it because ENABLE_PREPROCESSING is NO. - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class testing::internal::FindFirstPrinter< T, E, Printers... >! - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class FindFirstPrinter< T, E, Printers... >! - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class testing::internal::FindFirstPrinter< T, E, Printers... >! - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class FindFirstPrinter< T, E, Printers... >! - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-cardinalities.cc:129: warning: documented symbol 'void testing::Cardinality::DescribeActualCallCountTo' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:248: warning: documented symbol 'bool testing::internal::MatchMatrix::NextGraph' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:262: warning: documented symbol 'void testing::internal::MatchMatrix::Randomize' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:271: warning: no uniquely matching class member found for - std::string testing::internal::MatchMatrix::DebugString() const - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:284: warning: documented symbol 'void testing::internal::UnorderedElementsAreMatcherImplBase::DescribeToImpl' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:325: warning: documented symbol 'void testing::internal::UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:371: warning: documented symbol 'bool testing::internal::UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:421: warning: documented symbol 'bool testing::internal::UnorderedElementsAreMatcherImplBase::FindPairing' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:82: warning: documented symbol 'testing::internal::ExpectationBase::ExpectationBase' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:98: warning: documented symbol 'testing::internal::ExpectationBase::~ExpectationBase' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:102: warning: documented symbol 'void testing::internal::ExpectationBase::SpecifyCardinality' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:108: warning: documented symbol 'void testing::internal::ExpectationBase::RetireAllPreRequisites' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:135: warning: documented symbol 'bool testing::internal::ExpectationBase::AllPrerequisitesAreSatisfied' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:155: warning: documented symbol 'void testing::internal::ExpectationBase::FindUnsatisfiedPrerequisites' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:186: warning: documented symbol 'void testing::internal::ExpectationBase::DescribeCallCountTo' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:209: warning: documented symbol 'void testing::internal::ExpectationBase::CheckActionCountIfNotDone' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:261: warning: documented symbol 'void testing::internal::ExpectationBase::UntypedTimes' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:308: warning: documented symbol 'testing::internal::UntypedFunctionMockerBase::UntypedFunctionMockerBase' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:311: warning: documented symbol 'testing::internal::UntypedFunctionMockerBase::~UntypedFunctionMockerBase' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:317: warning: documented symbol 'void testing::internal::UntypedFunctionMockerBase::RegisterOwner' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:329: warning: documented symbol 'void testing::internal::UntypedFunctionMockerBase::SetOwnerAndName' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:341: warning: documented symbol 'const void * testing::internal::UntypedFunctionMockerBase::MockObject' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:358: warning: documented symbol 'const char * testing::internal::UntypedFunctionMockerBase::Name' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:376: warning: documented symbol 'UntypedActionResultHolderBase * testing::internal::UntypedFunctionMockerBase::UntypedInvokeWith' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:505: warning: documented symbol 'Expectation testing::internal::UntypedFunctionMockerBase::GetHandleOf' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:525: warning: documented symbol 'bool testing::internal::UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:685: warning: documented symbol 'void Mock::AllowUninterestingCalls' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:692: warning: documented symbol 'void Mock::WarnUninterestingCalls' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:699: warning: documented symbol 'void Mock::FailUninterestingCalls' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:706: warning: documented symbol 'void Mock::UnregisterCallReaction' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:714: warning: documented symbol 'internal::CallReaction Mock::GetReactionOnUninterestingCalls' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:726: warning: documented symbol 'void Mock::AllowLeak' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:735: warning: documented symbol 'bool Mock::VerifyAndClearExpectations' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:744: warning: documented symbol 'bool Mock::VerifyAndClear' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:754: warning: documented symbol 'bool Mock::VerifyAndClearExpectationsLocked' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:779: warning: documented symbol 'bool Mock::IsNaggy' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:783: warning: documented symbol 'bool Mock::IsNice' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:787: warning: documented symbol 'bool Mock::IsStrict' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:793: warning: no uniquely matching class member found for - void Mock::Register(const void *mock_obj, internal::UntypedFunctionMockerBase *mocker) - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:803: warning: documented symbol 'void Mock::RegisterUseByOnCallOrExpectCall' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:824: warning: documented symbol 'void Mock::UnregisterLocked' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:842: warning: documented symbol 'void Mock::ClearDefaultActionsLocked' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:864: warning: documented symbol 'testing::Expectation::Expectation' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:866: warning: documented symbol 'testing::Expectation::Expectation' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:870: warning: documented symbol 'testing::Expectation::~Expectation' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:873: warning: documented symbol 'void testing::Sequence::AddExpectation' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:884: warning: documented symbol 'testing::InSequence::InSequence' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:895: warning: documented symbol 'testing::InSequence::~InSequence' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h:111: warning: no matching file member found for -std::string testing::PrintToString(const T &value) +warning: source 'images' is not a readable file or directory... skipping. +d:/PlatformIO/linear-algebra/Quaternion.cpp:100: warning: no uniquely matching class member found for + Quaternion Quaternion::operator*(const Quaternion &r2) const Possible candidates: - '::std::string PrintToString(const T &value)' at line 1037 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h:160: warning: no matching file member found for -testing::internal::GTEST_DISABLE_MSC_WARNINGS_PUSH_ + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(const AngleOf< T > &a, float f)' at line 48 of file d:/PlatformIO/linear-algebra/Angle.h + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(float f, const AngleOf< T > &a)' at line 51 of file d:/PlatformIO/linear-algebra/Angle.h + 'Vector3 Passer::LinearAlgebra::MatrixOf< T >::operator*(const Vector3 v) const' at line 64 of file d:/PlatformIO/linear-algebra/Matrix.h + 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(const PolarOf &v, float f)' at line 100 of file d:/PlatformIO/linear-algebra/Polar.h + 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(float f, const PolarOf &v)' at line 103 of file d:/PlatformIO/linear-algebra/Polar.h + 'Vector3 Passer::LinearAlgebra::Quaternion::operator*(const Vector3 &vector) const' at line 98 of file d:/PlatformIO/linear-algebra/Quaternion.h + 'Quaternion Passer::LinearAlgebra::Quaternion::operator*(const Quaternion &rotation) const' at line 106 of file d:/PlatformIO/linear-algebra/Quaternion.h + 'friend SphericalOf< T > Passer::LinearAlgebra::SphericalOf< T >::operator*(const SphericalOf< T > &v, float f)' at line 109 of file d:/PlatformIO/linear-algebra/Spherical.h + 'friend SphericalOf< T > Passer::LinearAlgebra::SphericalOf< T >::operator*(float f, const SphericalOf< T > &v)' at line 112 of file d:/PlatformIO/linear-algebra/Spherical.h + 'SphericalOf< T > Passer::LinearAlgebra::SwingTwistOf< T >::operator*(const SphericalOf< T > &vector) const' at line 45 of file d:/PlatformIO/linear-algebra/SwingTwist.h + 'SwingTwistOf< T > Passer::LinearAlgebra::SwingTwistOf< T >::operator*(const SwingTwistOf< T > &rotation) const' at line 53 of file d:/PlatformIO/linear-algebra/SwingTwist.h + 'friend Vector2 Passer::LinearAlgebra::Vector2::operator*(const Vector2 &v, float f)' at line 143 of file d:/PlatformIO/linear-algebra/Vector2.h + 'friend Vector2 Passer::LinearAlgebra::Vector2::operator*(float f, const Vector2 &v)' at line 146 of file d:/PlatformIO/linear-algebra/Vector2.h + 'friend Vector3 Passer::LinearAlgebra::Vector3::operator*(const Vector3 &v, float f)' at line 151 of file d:/PlatformIO/linear-algebra/Vector3.h + 'friend Vector3 Passer::LinearAlgebra::Vector3::operator*(float f, const Vector3 &v)' at line 154 of file d:/PlatformIO/linear-algebra/Vector3.h +d:/PlatformIO/linear-algebra/Quaternion.cpp:108: warning: no uniquely matching class member found for + Vector3 Quaternion::operator*(const Vector3 &p) const Possible candidates: - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 48 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-cardinalities.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 GMOCK_MAYBE_5046_) namespace testing' at line 283 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-matchers.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 84 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-spec-builders.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 GTEST_MAYBE_5046_) namespace testing' at line 59 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-matchers.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 38 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-spi.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 42 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-test-part.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) GTEST_DECLARE_bool_(also_run_disabled_tests)' at line 72 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) class GTEST_API_ DeathTest' at line 60 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-death-test-internal.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 47 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-filepath.h - 'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) GTEST_DECLARE_bool_(death_test_use_fork)' at line 64 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-internal-inl.h - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-assertion-result.cc:59: warning: documented symbol 'AssertionResult testing::AssertionResult::operator!' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:373: warning: documented symbol 'testing::internal::DeathTest::DeathTest' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:383: warning: no matching class member found for - bool testing::internal::DeathTest::Create(const char *statement, Matcher< const std::string & > matcher, const char *file, int line, DeathTest **test) - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:390: warning: documented symbol 'const char * testing::internal::DeathTest::LastMessage' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:394: warning: documented symbol 'void testing::internal::DeathTest::set_last_death_test_message' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:398: warning: documented symbol 'std::string testing::internal::DeathTest::last_death_test_message_' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:94: warning: documented symbol 'FilePath testing::internal::FilePath::GetCurrentDir' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:121: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveExtension' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:133: warning: documented symbol 'const char * testing::internal::FilePath::FindLastPathSeparator' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:152: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveDirectoryName' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:163: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveFileName' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:180: warning: documented symbol 'FilePath testing::internal::FilePath::MakeFileName' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:196: warning: documented symbol 'FilePath testing::internal::FilePath::ConcatPaths' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:206: warning: documented symbol 'bool testing::internal::FilePath::FileOrDirectoryExists' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:220: warning: documented symbol 'bool testing::internal::FilePath::DirectoryExists' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:250: warning: documented symbol 'bool testing::internal::FilePath::IsRootDirectory' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:259: warning: documented symbol 'bool testing::internal::FilePath::IsAbsolutePath' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:280: warning: documented symbol 'FilePath testing::internal::FilePath::GenerateUniqueFileName' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:294: warning: documented symbol 'bool testing::internal::FilePath::IsDirectory' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:302: warning: documented symbol 'bool testing::internal::FilePath::CreateDirectoriesRecursively' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:319: warning: documented symbol 'bool testing::internal::FilePath::CreateFolder' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:343: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveTrailingPathSeparator' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:352: warning: no uniquely matching class member found for - void testing::internal::FilePath::Normalize() - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:45: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:49: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:55: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:59: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:64: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:70: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:76: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:82: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:86: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:92: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-port.cc:301: warning: no matching class member found for - void testing::internal::AutoHandle::Reset(HANDLE handle) + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(const AngleOf< T > &a, float f)' at line 48 of file d:/PlatformIO/linear-algebra/Angle.h + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(float f, const AngleOf< T > &a)' at line 51 of file d:/PlatformIO/linear-algebra/Angle.h + 'Vector3 Passer::LinearAlgebra::MatrixOf< T >::operator*(const Vector3 v) const' at line 64 of file d:/PlatformIO/linear-algebra/Matrix.h + 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(const PolarOf &v, float f)' at line 100 of file d:/PlatformIO/linear-algebra/Polar.h + 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(float f, const PolarOf &v)' at line 103 of file d:/PlatformIO/linear-algebra/Polar.h + 'Vector3 Passer::LinearAlgebra::Quaternion::operator*(const Vector3 &vector) const' at line 98 of file d:/PlatformIO/linear-algebra/Quaternion.h + 'Quaternion Passer::LinearAlgebra::Quaternion::operator*(const Quaternion &rotation) const' at line 106 of file d:/PlatformIO/linear-algebra/Quaternion.h + 'friend SphericalOf< T > Passer::LinearAlgebra::SphericalOf< T >::operator*(const SphericalOf< T > &v, float f)' at line 109 of file d:/PlatformIO/linear-algebra/Spherical.h + 'friend SphericalOf< T > Passer::LinearAlgebra::SphericalOf< T >::operator*(float f, const SphericalOf< T > &v)' at line 112 of file d:/PlatformIO/linear-algebra/Spherical.h + 'SphericalOf< T > Passer::LinearAlgebra::SwingTwistOf< T >::operator*(const SphericalOf< T > &vector) const' at line 45 of file d:/PlatformIO/linear-algebra/SwingTwist.h + 'SwingTwistOf< T > Passer::LinearAlgebra::SwingTwistOf< T >::operator*(const SwingTwistOf< T > &rotation) const' at line 53 of file d:/PlatformIO/linear-algebra/SwingTwist.h + 'friend Vector2 Passer::LinearAlgebra::Vector2::operator*(const Vector2 &v, float f)' at line 143 of file d:/PlatformIO/linear-algebra/Vector2.h + 'friend Vector2 Passer::LinearAlgebra::Vector2::operator*(float f, const Vector2 &v)' at line 146 of file d:/PlatformIO/linear-algebra/Vector2.h + 'friend Vector3 Passer::LinearAlgebra::Vector3::operator*(const Vector3 &v, float f)' at line 151 of file d:/PlatformIO/linear-algebra/Vector3.h + 'friend Vector3 Passer::LinearAlgebra::Vector3::operator*(float f, const Vector3 &v)' at line 154 of file d:/PlatformIO/linear-algebra/Vector3.h +d:/PlatformIO/linear-algebra/Quaternion.cpp:152: warning: no uniquely matching class member found for + Quaternion Quaternion::LookRotation(const Vector3 &forward, const Vector3 &up) Possible candidates: - 'void testing::internal::AutoHandle::Reset()' - 'void testing::internal::AutoHandle::Reset(Handle handle)' - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:44: warning: documented symbol 'std::string testing::TestPartResult::ExtractSummary' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:66: warning: no uniquely matching class member found for - void testing::TestPartResultArray::Append(const TestPartResult &result) - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:71: warning: no matching class member found for - const TestPartResult & testing::TestPartResultArray::GetTestPartResult(int index) const - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:81: warning: no uniquely matching class member found for - int testing::TestPartResultArray::size() const - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:87: warning: documented symbol 'testing::internal::HasNewFatalFailureHelper::HasNewFatalFailureHelper' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:94: warning: documented symbol 'testing::internal::HasNewFatalFailureHelper::~HasNewFatalFailureHelper' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:99: warning: no uniquely matching class member found for - void testing::internal::HasNewFatalFailureHelper::ReportTestPartResult(const TestPartResult &result) - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-typed-test.cc:58: warning: documented symbol 'const char * testing::internal::TypedTestSuitePState::VerifyRegisteredTestNames' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:858: warning: documented symbol 'testing::ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:868: warning: documented symbol 'testing::ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:875: warning: no uniquely matching class member found for - void testing::ScopedFakeTestPartResultReporter::Init() - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:888: warning: documented symbol 'testing::ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:899: warning: no uniquely matching class member found for - void testing::ScopedFakeTestPartResultReporter::ReportTestPartResult(const TestPartResult &result) - -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:965: warning: documented symbol 'testing::internal::SingleFailureChecker::SingleFailureChecker' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:974: warning: documented symbol 'testing::internal::SingleFailureChecker::~SingleFailureChecker' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:2602: warning: documented symbol 'testing::internal::GoogleTestFailureException::GoogleTestFailureException' was not declared or defined. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:52: warning: explicit link request to 'testing::AssertionResult' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:229: warning: explicit link request to 'Bar()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:283: warning: explicit link request to 'testing::Environment' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:283: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:376: warning: explicit link request to 'testing::PrintToString(x)' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:786: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:813: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:850: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:953: warning: explicit link request to 'testing::Environment' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:970: warning: explicit link request to 'testing::AddGlobalTestEnvironment()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1243: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1364: warning: explicit link request to 'testing::Types' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1397: warning: explicit link request to 'including' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1496: warning: explicit link request to 'including' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1538: warning: explicit link request to 'testing::RegisterTest' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1764: warning: explicit link request to 'testing::InitGoogleTest()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1813: warning: found at different nesting level (5) than expected (2) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1822: warning: found tag while expecting -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1823: warning: found tag while expecting -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1824: warning: found tag while expecting -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1986: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1986: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1987: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1987: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1988: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1988: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1989: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1989: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1990: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1990: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1991: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1991: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1992: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1992: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1994: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1994: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1996: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1996: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1997: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1997: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1998: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1998: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1999: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1999: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:2000: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:2000: warning: Unsupported xml/html tag found -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:2380: warning: end of comment block while expecting command -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/faq.md:658: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cheat_sheet.md:6: warning: found subsection command (id: 'MockClass') outside of section context! -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:9: warning: explicit link request to 'testing::Foo' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:186: warning: found subsection command (id: 'MockingNonVirtualMethods') outside of section context! -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:1540: warning: explicit link request to 'Set()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:1950: warning: explicit link request to 'testing::ActionInterface' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2045: warning: explicit link request to 'testing::InSequence' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2098: warning: explicit link request to 'testing::DefaultValue' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2223: warning: explicit link request to 'testing::Invoke' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2309: warning: explicit link request to 'testing::InvokeWithoutArgs' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:4107: warning: explicit link request to 'testing::ActionInterface' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_for_dummies.md:524: warning: found subsection command (id: 'MultiExpectations') outside of section context! -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/primer.md:213: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/primer.md:457: warning: explicit link request to 'testing::InitGoogleTest()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/actions.md:5: warning: explicit link request to 'testing' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/assertions.md:529: warning: explicit link request to 'testing::GTEST_FLAG(death_test_style)' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/matchers.md:20: warning: explicit link request to 'testing' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/matchers.md:145: warning: explicit link request to 'std::tuple' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:92: warning: explicit link request to 'EXPECT_CALL.With' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:122: warning: explicit link request to 'EXPECT_CALL.Times' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:129: warning: explicit link request to 'testing' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:151: warning: explicit link request to 'EXPECT_CALL.InSequence' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:181: warning: explicit link request to 'EXPECT_CALL.After' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:222: warning: explicit link request to 'EXPECT_CALL.WillOnce' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:253: warning: explicit link request to 'EXPECT_CALL.WillRepeatedly' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:286: warning: explicit link request to 'EXPECT_CALL.RetiresOnSaturation' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:347: warning: explicit link request to 'ON_CALL.With' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:378: warning: explicit link request to 'ON_CALL.WillByDefault' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:413: warning: explicit link request to 'testing::DefaultValue' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:437: warning: explicit link request to 'testing::NiceMock' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:468: warning: explicit link request to 'testing::NaggyMock' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:495: warning: explicit link request to 'testing::StrictMock' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:527: warning: explicit link request to 'testing::Sequence' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:534: warning: explicit link request to 'testing::InSequence' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:559: warning: explicit link request to 'testing::Expectation' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:574: warning: explicit link request to 'testing::ExpectationSet' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:13: warning: found subsection command (id: 'TEST') outside of section context! -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:100: warning: explicit link request to 'testing' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:389: warning: explicit link request to 'testing::AssertionResult' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:403: warning: explicit link request to 'testing::AssertionException' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:410: warning: explicit link request to 'testing::EmptyTestEventListener' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:418: warning: explicit link request to 'testing::Environment' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:425: warning: explicit link request to 'Environment::SetUp' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:431: warning: explicit link request to 'Environment::TearDown' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:439: warning: explicit link request to 'testing::ScopedTrace' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:466: warning: explicit link request to 'testing::Test' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:472: warning: explicit link request to 'Test::SetUpTestSuite' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:479: warning: explicit link request to 'Test::TearDownTestSuite' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:486: warning: explicit link request to 'Test::HasFatalFailure' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:492: warning: explicit link request to 'Test::HasNonfatalFailure' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:498: warning: explicit link request to 'Test::HasFailure' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:505: warning: explicit link request to 'Test::IsSkipped' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:511: warning: explicit link request to 'Test::RecordProperty' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:538: warning: explicit link request to 'Test::SetUp' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:545: warning: explicit link request to 'Test::TearDown' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:554: warning: explicit link request to 'testing::TestWithParam' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:565: warning: explicit link request to 'TestSuite::name' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:571: warning: explicit link request to 'TestSuite::type_param' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:579: warning: explicit link request to 'TestSuite::should_run' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:585: warning: explicit link request to 'TestSuite::successful_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:591: warning: explicit link request to 'TestSuite::skipped_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:597: warning: explicit link request to 'TestSuite::failed_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:603: warning: explicit link request to 'TestSuite::reportable_disabled_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:609: warning: explicit link request to 'TestSuite::disabled_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:615: warning: explicit link request to 'TestSuite::reportable_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:621: warning: explicit link request to 'TestSuite::test_to_run_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:627: warning: explicit link request to 'TestSuite::total_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:633: warning: explicit link request to 'TestSuite::Passed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:639: warning: explicit link request to 'TestSuite::Failed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:645: warning: explicit link request to 'TestSuite::elapsed_time' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:651: warning: explicit link request to 'TestSuite::start_timestamp' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:657: warning: explicit link request to 'TestSuite::GetTestInfo' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:665: warning: explicit link request to 'TestSuite::ad_hoc_test_result' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:674: warning: explicit link request to 'testing::TestInfo' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:680: warning: explicit link request to 'TestInfo::test_suite_name' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:686: warning: explicit link request to 'TestInfo::name' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:692: warning: explicit link request to 'TestInfo::type_param' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:700: warning: explicit link request to 'TestInfo::value_param' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:708: warning: explicit link request to 'TestInfo::file' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:714: warning: explicit link request to 'TestInfo::line' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:720: warning: explicit link request to 'TestInfo::is_in_another_shard' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:726: warning: explicit link request to 'TestInfo::should_run' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:739: warning: explicit link request to 'TestInfo::is_reportable' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:745: warning: explicit link request to 'TestInfo::result' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:753: warning: explicit link request to 'testing::TestParamInfo' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:763: warning: explicit link request to 'testing::UnitTest' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:774: warning: explicit link request to 'UnitTest::GetInstance' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:782: warning: explicit link request to 'UnitTest::original_working_dir' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:789: warning: explicit link request to 'UnitTest::current_test_suite' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:796: warning: explicit link request to 'UnitTest::current_test_info' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:803: warning: explicit link request to 'UnitTest::random_seed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:809: warning: explicit link request to 'UnitTest::successful_test_suite_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:815: warning: explicit link request to 'UnitTest::failed_test_suite_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:821: warning: explicit link request to 'UnitTest::total_test_suite_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:827: warning: explicit link request to 'UnitTest::test_suite_to_run_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:834: warning: explicit link request to 'UnitTest::successful_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:840: warning: explicit link request to 'UnitTest::skipped_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:846: warning: explicit link request to 'UnitTest::failed_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:852: warning: explicit link request to 'UnitTest::reportable_disabled_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:858: warning: explicit link request to 'UnitTest::disabled_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:864: warning: explicit link request to 'UnitTest::reportable_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:870: warning: explicit link request to 'UnitTest::total_test_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:876: warning: explicit link request to 'UnitTest::test_to_run_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:882: warning: explicit link request to 'UnitTest::start_timestamp' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:888: warning: explicit link request to 'UnitTest::elapsed_time' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:894: warning: explicit link request to 'UnitTest::Passed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:900: warning: explicit link request to 'UnitTest::Failed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:907: warning: explicit link request to 'UnitTest::GetTestSuite' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:915: warning: explicit link request to 'UnitTest::ad_hoc_test_result' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:922: warning: explicit link request to 'UnitTest::listeners' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:931: warning: explicit link request to 'testing::TestEventListener' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:938: warning: explicit link request to 'TestEventListener::OnTestProgramStart' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:944: warning: explicit link request to 'TestEventListener::OnTestIterationStart' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:953: warning: explicit link request to 'TestEventListener::OnEnvironmentsSetUpStart' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:960: warning: explicit link request to 'TestEventListener::OnEnvironmentsSetUpEnd' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:967: warning: explicit link request to 'TestEventListener::OnTestSuiteStart' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:973: warning: explicit link request to 'TestEventListener::OnTestStart' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:979: warning: explicit link request to 'TestEventListener::OnTestPartResult' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:988: warning: explicit link request to 'TestEventListener::OnTestEnd' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:994: warning: explicit link request to 'TestEventListener::OnTestSuiteEnd' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1000: warning: explicit link request to 'TestEventListener::OnEnvironmentsTearDownStart' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1007: warning: explicit link request to 'TestEventListener::OnEnvironmentsTearDownEnd' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1014: warning: explicit link request to 'TestEventListener::OnTestIterationEnd' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1021: warning: explicit link request to 'TestEventListener::OnTestProgramEnd' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1029: warning: explicit link request to 'testing::TestEventListeners' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1035: warning: explicit link request to 'TestEventListeners::Append' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1043: warning: explicit link request to 'TestEventListeners::Release' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1051: warning: explicit link request to 'TestEventListeners::default_result_printer' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1061: warning: explicit link request to 'TestEventListeners::default_xml_generator' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1074: warning: explicit link request to 'testing::TestPartResult' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1081: warning: explicit link request to 'TestPartResult::type' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1098: warning: explicit link request to 'TestPartResult::file_name' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1105: warning: explicit link request to 'TestPartResult::line_number' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1112: warning: explicit link request to 'TestPartResult::summary' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1118: warning: explicit link request to 'TestPartResult::message' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1124: warning: explicit link request to 'TestPartResult::skipped' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1130: warning: explicit link request to 'TestPartResult::passed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1136: warning: explicit link request to 'TestPartResult::nonfatally_failed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1142: warning: explicit link request to 'TestPartResult::fatally_failed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1148: warning: explicit link request to 'TestPartResult::failed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1156: warning: explicit link request to 'testing::TestProperty' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1183: warning: explicit link request to 'testing::TestResult' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1191: warning: explicit link request to 'TestResult::total_part_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1198: warning: explicit link request to 'TestResult::test_property_count' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1204: warning: explicit link request to 'TestResult::Passed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1210: warning: explicit link request to 'TestResult::Skipped' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1216: warning: explicit link request to 'TestResult::Failed' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1222: warning: explicit link request to 'TestResult::HasFatalFailure' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1228: warning: explicit link request to 'TestResult::HasNonfatalFailure' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1234: warning: explicit link request to 'TestResult::elapsed_time' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1240: warning: explicit link request to 'TestResult::start_timestamp' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1246: warning: explicit link request to 'TestResult::GetTestPartResult' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1254: warning: explicit link request to 'TestResult::GetTestProperty' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1264: warning: explicit link request to 'testing::TimeInMillis' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1270: warning: explicit link request to 'testing::Types' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1286: warning: explicit link request to 'testing::WithParamInterface' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1312: warning: explicit link request to 'testing::InitGoogleTest(int* argc, char** argv)' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1313: warning: explicit link request to 'testing::InitGoogleTest(int* argc, wchar_t** argv)' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1314: warning: explicit link request to 'testing::InitGoogleTest()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1331: warning: explicit link request to 'testing::AddGlobalTestEnvironment(Environment* env)' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1383: warning: explicit link request to 'testing::AssertionSuccess()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1390: warning: explicit link request to 'testing::AssertionFailure()' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1403: warning: explicit link request to 'testing::StaticAssertTypeEq' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1412: warning: explicit link request to 'testing::PrintToString(x)' could not be resolved -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1422: warning: explicit link request to 'testing::PrintToStringParamName' could not be resolved -D:/C/VectorAlgebra/include/Vector2.h:233: warning: Member ToFactor(Vector2 a, Vector2 b) (function) of struct Vector2 is not documented. -D:/C/VectorAlgebra/include/Vector2.h:205: warning: argument 'axis' of command @param is not found in the argument list of Vector2::SignedAngle(Vector2 from, Vector2 to) -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:119: warning: Member testCatchesCxxExceptionsInFixtureConstructor(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:133: warning: Member testCatchesCxxExceptionsInFixtureDestructor(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:143: warning: Member testCatchesCxxExceptionsInSetUpTestCase(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:166: warning: Member testCatchesCxxExceptionsInTearDownTestCase(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:171: warning: Member testCatchesCxxExceptionsInSetUp(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:189: warning: Member testCatchesCxxExceptionsInTearDown(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:200: warning: Member testCatchesCxxExceptionsInTestBody(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:214: warning: Member testCatchesNonStdCxxExceptions(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:219: warning: Member testUnhandledCxxExceptionsAbortTheProgram(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:85: warning: Member TestSehExceptions(self, test_output) (function) of class googletest-catch-exceptions-test::CatchSehExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:103: warning: Member testCatchesSehExceptionsWithCxxExceptionsEnabled(self) (function) of class googletest-catch-exceptions-test::CatchSehExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:106: warning: Member testCatchesSehExceptionsWithCxxExceptionsDisabled(self) (function) of class googletest-catch-exceptions-test::CatchSehExceptionsTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:122: warning: Member testGoogletestFlag(self) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:187: warning: Member testEventListener(self) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:214: warning: Member assertXmlResultCount(self, result, count, xml) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:220: warning: Member assertXmlStatusCount(self, status, count, xml) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-filter-unittest.py:517: warning: Member testNegativeFilters(self) (function) of class googletest-filter-unittest::GTestFilterUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:134: warning: Member setUp(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:142: warning: Member tearDown(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:145: warning: Member DeleteFilesAndDir(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:159: warning: Member testOutfile1(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:162: warning: Member testOutfile2(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:138: warning: Member output_dir_ (variable) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:170: warning: Member setUp(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:173: warning: Member testShufflePreservesNumberOfTests(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:179: warning: Member testShuffleChangesTestOrder(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:187: warning: Member testShuffleChangesTestCaseOrder(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:200: warning: Member testShuffleDoesNotRepeatTest(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:214: warning: Member testShuffleDoesNotCreateNewTest(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:224: warning: Member testShuffleIncludesAllTests(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:234: warning: Member testShuffleLeavesDeathTestsAtFront(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:253: warning: Member testShuffleDoesNotInterleaveTestCases(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:259: warning: Member testShuffleRestoresOrderAfterEachIteration(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:291: warning: Member testShuffleGeneratesNewOrderInEachIteration(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:303: warning: Member testShuffleShardedTestsPreservesPartition(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:140: warning: Member testPrintsHelpWithFullFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:143: warning: Member testPrintsHelpWithShortFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:146: warning: Member testPrintsHelpWithQuestionFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:149: warning: Member testPrintsHelpWithWindowsStyleQuestionFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:152: warning: Member testPrintsHelpWithUnrecognizedGoogleTestFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:155: warning: Member testPrintsHelpWithIncorrectFlagStyle(self) (function) of class gtest_help_test::GTestHelpTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:75: warning: Member setUp(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:83: warning: Member tearDown(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:86: warning: Member DeleteFilesAndDir(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:100: warning: Member testOutfile1(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:103: warning: Member testOutfile2(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:79: warning: Member output_dir_ (variable) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented. -D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_test_utils.py:103: warning: Member identifying_attribute (variable) of class gtest_xml_test_utils::GTestXMLTestCase is not documented. + 'static Quaternion Passer::LinearAlgebra::Quaternion::LookRotation(const Vector3 &forward, const Vector3 &upwards)' at line 132 of file d:/PlatformIO/linear-algebra/Quaternion.h + 'static Quaternion Passer::LinearAlgebra::Quaternion::LookRotation(const Vector3 &forward)' at line 143 of file d:/PlatformIO/linear-algebra/Quaternion.h +d:/PlatformIO/linear-algebra/Quaternion.cpp:330: warning: no uniquely matching class member found for + Quaternion Quaternion::Euler(Vector3 euler) +Possible candidates: + 'static Quaternion Passer::LinearAlgebra::Quaternion::Euler(float x, float y, float z)' at line 218 of file d:/PlatformIO/linear-algebra/Quaternion.h + 'static Quaternion Passer::LinearAlgebra::Quaternion::Euler(Vector3 eulerAngles)' at line 225 of file d:/PlatformIO/linear-algebra/Quaternion.h +d:/PlatformIO/linear-algebra/Quaternion.cpp:362: warning: no uniquely matching class member found for + Quaternion Quaternion::EulerXYZ(Vector3 euler) +Possible candidates: + 'static Quaternion Passer::LinearAlgebra::Quaternion::EulerXYZ(float x, float y, float z)' at line 235 of file d:/PlatformIO/linear-algebra/Quaternion.h + 'static Quaternion Passer::LinearAlgebra::Quaternion::EulerXYZ(Vector3 eulerAngles)' at line 242 of file d:/PlatformIO/linear-algebra/Quaternion.h +d:/PlatformIO/linear-algebra/Spherical.cpp:137: warning: no uniquely matching class member found for + template < T > + SphericalOf< T > SphericalOf::operator-(const SphericalOf< T > &s2) const +Possible candidates: + 'AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator-() const' at line 43 of file d:/PlatformIO/linear-algebra/Angle.h + 'AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator-(const AngleOf< T > &a) const' at line 44 of file d:/PlatformIO/linear-algebra/Angle.h + 'DirectionOf< T > Passer::LinearAlgebra::DirectionOf< T >::operator-() const' at line 41 of file d:/PlatformIO/linear-algebra/Direction.h + 'PolarOf Passer::LinearAlgebra::PolarOf< T >::operator-() const' at line 82 of file d:/PlatformIO/linear-algebra/Polar.h + 'PolarOf Passer::LinearAlgebra::PolarOf< T >::operator-(const PolarOf &v) const' at line 87 of file d:/PlatformIO/linear-algebra/Polar.h + 'RangeUsing< T > Passer::LinearAlgebra::RangeUsing< T >::operator-(RangeUsing< T > a)' at line 38 of file d:/PlatformIO/linear-algebra/Range.h + 'RangeUsing< T > Passer::LinearAlgebra::RangeUsing< T >::operator-()' at line 40 of file d:/PlatformIO/linear-algebra/Range.h + 'SphericalOf< T > Passer::LinearAlgebra::SphericalOf< T >::operator-() const' at line 91 of file d:/PlatformIO/linear-algebra/Spherical.h + 'SphericalOf< T > Passer::LinearAlgebra::SphericalOf< T >::operator-(const SphericalOf< T > &v) const' at line 96 of file d:/PlatformIO/linear-algebra/Spherical.h + 'Vector2 Passer::LinearAlgebra::Vector2::operator-()' at line 118 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Vector2 Passer::LinearAlgebra::Vector2::operator-(const Vector2 &v) const' at line 123 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Vector3 Passer::LinearAlgebra::Vector3::operator-() const' at line 126 of file d:/PlatformIO/linear-algebra/Vector3.h + 'Vector3 Passer::LinearAlgebra::Vector3::operator-(const Vector3 &v) const' at line 131 of file d:/PlatformIO/linear-algebra/Vector3.h +d:/PlatformIO/linear-algebra/Vector2.cpp:20: warning: no uniquely matching class member found for + Vector2::Vector2(float _x, float _y) +Possible candidates: + 'Passer::LinearAlgebra::Vector2::Vector2()' at line 45 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Passer::LinearAlgebra::Vector2::Vector2(float right, float forward)' at line 49 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Passer::LinearAlgebra::Vector2::Vector2(Vector3 v)' at line 53 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Passer::LinearAlgebra::Vector2::Vector2(PolarOf< float > v)' at line 56 of file d:/PlatformIO/linear-algebra/Vector2.h +d:/PlatformIO/linear-algebra/Vector2.cpp:32: warning: no uniquely matching class member found for + Vector2::Vector2(Polar p) +Possible candidates: + 'Passer::LinearAlgebra::Vector2::Vector2()' at line 45 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Passer::LinearAlgebra::Vector2::Vector2(float right, float forward)' at line 49 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Passer::LinearAlgebra::Vector2::Vector2(Vector3 v)' at line 53 of file d:/PlatformIO/linear-algebra/Vector2.h + 'Passer::LinearAlgebra::Vector2::Vector2(PolarOf< float > v)' at line 56 of file d:/PlatformIO/linear-algebra/Vector2.h +d:/PlatformIO/linear-algebra/Vector3.cpp:33: warning: no uniquely matching class member found for + Vector3::Vector3(SphericalOf< float > s) +Possible candidates: + 'Passer::LinearAlgebra::Vector3::Vector3()' at line 49 of file d:/PlatformIO/linear-algebra/Vector3.h + 'Passer::LinearAlgebra::Vector3::Vector3(float right, float up, float forward)' at line 54 of file d:/PlatformIO/linear-algebra/Vector3.h + 'Passer::LinearAlgebra::Vector3::Vector3(Vector2 v)' at line 57 of file d:/PlatformIO/linear-algebra/Vector3.h + 'Passer::LinearAlgebra::Vector3::Vector3(SphericalOf< float > v)' at line 61 of file d:/PlatformIO/linear-algebra/Vector3.h +d:/PlatformIO/linear-algebra/Matrix.h:12: warning: Member MatrixOf(unsigned int rows, unsigned int cols) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:13: warning: Member MatrixOf(unsigned int rows, unsigned int cols, const T *source) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:17: warning: Member MatrixOf(Vector3 v) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:59: warning: Member Multiply(const MatrixOf< T > *m, MatrixOf< T > *r) const (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:64: warning: Member operator*(const Vector3 v) const (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:66: warning: Member Get(unsigned int rowIx, unsigned int colIx) const (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:71: warning: Member Set(unsigned int rowIx, unsigned int colIx, T value) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:77: warning: Member Set(const T *source) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:84: warning: Member SetRow(unsigned int rowIx, const T *source) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:91: warning: Member SetCol(unsigned int colIx, const T *source) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:98: warning: Member CopyFrom(const MatrixOf< T > *m) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:108: warning: Member RowCount() const (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:109: warning: Member ColCount() const (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:57: warning: Member Multiply(const MatrixOf< T > *m1, const MatrixOf< T > *m2, MatrixOf< T > *r) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Matrix.h:63: warning: Member Multiply(const MatrixOf< T > *m, Vector3 v) (function) of class Passer::LinearAlgebra::MatrixOf is not documented. +d:/PlatformIO/linear-algebra/Vector2.h:124: warning: Member operator-=(const Vector2 &v) (function) of struct Passer::LinearAlgebra::Vector2 is not documented. +d:/PlatformIO/linear-algebra/Vector2.h:129: warning: Member operator+=(const Vector2 &v) (function) of struct Passer::LinearAlgebra::Vector2 is not documented. +d:/PlatformIO/linear-algebra/Vector2.h:150: warning: Member operator*=(float f) (function) of struct Passer::LinearAlgebra::Vector2 is not documented. +d:/PlatformIO/linear-algebra/Vector2.h:161: warning: Member operator/=(float f) (function) of struct Passer::LinearAlgebra::Vector2 is not documented. +d:/PlatformIO/linear-algebra/Vector2.h:146: warning: Member operator*(float f, const Vector2 &v) (friend) of struct Passer::LinearAlgebra::Vector2 is not documented. +d:/PlatformIO/linear-algebra/Vector2.h:158: warning: Member operator/(float f, const Vector2 &v) (friend) of struct Passer::LinearAlgebra::Vector2 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:84: warning: Member Forward() const (function) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:85: warning: Member Up() const (function) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:86: warning: Member Right() const (function) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:132: warning: Member operator-=(const Vector3 &v) (function) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:137: warning: Member operator+=(const Vector3 &v) (function) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:158: warning: Member operator*=(float f) (function) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:170: warning: Member operator/=(float f) (function) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:154: warning: Member operator*(float f, const Vector3 &v) (friend) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:166: warning: Member operator/(float f, const Vector3 &v) (friend) of struct Passer::LinearAlgebra::Vector3 is not documented. diff --git a/DoxyGen/Doxyfile b/DoxyGen/Doxyfile index 8f5e552..335a8f2 100644 --- a/DoxyGen/Doxyfile +++ b/DoxyGen/Doxyfile @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = VectorAlgebra +PROJECT_NAME = LinearAlgebra # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -58,7 +58,7 @@ PROJECT_LOGO = //intranet/home/Afbeeldingen/PasserVR/Logos/Logo3NameRi # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = //serrarens.nl/web/apis/VectorAlgebra +OUTPUT_DIRECTORY = //intranet/web/apis/LinearAlgebra # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -871,8 +871,7 @@ WARN_LOGFILE = DoxyWarnLogfile.txt # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../include \ - ../src \ +INPUT = .. \ ../README.md # This tag can be used to specify the character encoding of the source files @@ -978,7 +977,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = gtest*, googletest* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/README.md b/README.md index 42397d5..35bf50f 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ Vector algebra library Main components --------------- -* [Vector3](https://passervr.com/apis/VectorAlgebra/struct_vector3.html) -* [Quaternion](https://passervr.com/apis/VectorAlgebra/struct_quaternion.html) +* [Vector3](struct_passer_1_1_linear_algebra_1_1_vector3.html) +* [Quaternion](struct_passer_1_1_linear_algebra_1_1_quaternion.html) -* [Vector2](https://passervr.com/apis/VectorAlgebra/struct_vector2.html) +* [Vector2](https://serrarens.nl/apis/LinearAlgebra/struct_vector2.html) -* [Polar](https://passervr.com/apis/VectorAlgebra/struct_polar.html) +* [Polar](https://passervr.com/apis/LinearAlgebra/struct_polar.html) diff --git a/Spherical.cpp b/Spherical.cpp index 2b841f3..cde7654 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -33,6 +33,22 @@ SphericalOf::SphericalOf(float distance, DirectionOf direction) { } } +template +SphericalOf SphericalOf::Degrees(float distance, float horizontal, + float vertical) { + AngleOf horizontalAngle = AngleOf::Degrees(horizontal); + AngleOf verticalAngle = AngleOf::Degrees(vertical); + SphericalOf r = SphericalOf(distance, horizontalAngle, verticalAngle); + return r; +} + +template +SphericalOf SphericalOf::Radians(float distance, float horizontal, + float vertical) { + return SphericalOf(distance, AngleOf::Radians(horizontal), + AngleOf::Radians(vertical)); +} + template SphericalOf SphericalOf::FromPolar(PolarOf polar) { AngleOf horizontal = polar.angle; diff --git a/Spherical.h b/Spherical.h index 3d21bab..4d803bd 100644 --- a/Spherical.h +++ b/Spherical.h @@ -30,9 +30,38 @@ public: SphericalOf(float distance, AngleOf horizontal, AngleOf vertical); SphericalOf(float distance, DirectionOf direction); + /// @brief Create spherical vector without using AngleOf type. All given + /// angles are in degrees + /// @param distance The distance in meters + /// @param horizontal The horizontal angle in degrees + /// @param vertical The vertical angle in degrees + /// @return The spherical vector + static SphericalOf Degrees(float distance, float horizontal, + float vertical); + /// @brief Short-hand Deg alias for the Degrees function + constexpr static auto Deg = Degrees; + /// @brief Create sperical vector without using the AngleOf type. All given + /// angles are in radians + /// @param distance The distance in meters + /// @param horizontal The horizontal angle in radians + /// @param vertical The vertical angle in radians + /// @return The spherical vectpr + static SphericalOf Radians(float distance, float horizontal, + float vertical); + // Short-hand Rad alias for the Radians function + constexpr static auto Rad = Radians; + + /// @brief Create a Spherical coordinate from a Polar coordinate + /// @param v The polar coordinate + /// @return The spherical coordinate with the vertical angle set to zero. static SphericalOf FromPolar(PolarOf v); + /// @brief Create a Spherical coordinate from a Vector3 coordinate + /// @param v The vector coordinate + /// @return The spherical coordinate static SphericalOf FromVector3(Vector3 v); + /// @brief Convert the spherical coordinate to a Vector3 coordinate + /// @return The vector coordinate Vector3 ToVector3() const; /// @brief A spherical vector with zero degree angles and distance @@ -50,6 +79,9 @@ public: /// @brief A normalized down-oriented vector const static SphericalOf down; + /// @brief Update the distance component of the spherical coordinate + /// @param distance The new distance + /// @return The updated coordinate SphericalOf WithDistance(float distance); /// @brief Negate the vector @@ -94,23 +126,56 @@ public: } SphericalOf operator/=(float f); + /// @brief Calculate the distance between two spherical coordinates + /// @param v1 The first coordinate + /// @param v2 The second coordinate + /// @return The distance between the coordinates in meters static float DistanceBetween(const SphericalOf &v1, const SphericalOf &v2); + /// @brief Calculate the unsigned angle between two spherical vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The unsigned angle between the vectors static AngleOf AngleBetween(const SphericalOf &v1, const SphericalOf &v2); + /// @brief Calculate the signed angle between two spherical vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @param axis The axis are which the angle is calculated + /// @return The signed angle between the vectors static AngleOf SignedAngleBetween(const SphericalOf &v1, const SphericalOf &v2, const SphericalOf &axis); + /// @brief Rotate a spherical vector + /// @param v The vector to rotate + /// @param horizontalAngle The horizontal rotation angle in local space + /// @param verticalAngle The vertical rotation angle in local space + /// @return The rotated vector static SphericalOf Rotate(const SphericalOf &v, AngleOf horizontalAngle, AngleOf verticalAngle); + /// @brief Rotate a spherical vector horizontally + /// @param v The vector to rotate + /// @param angle The horizontal rotation angle in local space + /// @return The rotated vector static SphericalOf RotateHorizontal(const SphericalOf &v, AngleOf angle); + /// @brief Rotate a spherical vector vertically + /// @param v The vector to rotate + /// @param angle The vertical rotation angle in local space + /// @return The rotated vector static SphericalOf RotateVertical(const SphericalOf &v, AngleOf angle); }; +/// @brief Shorthand notation for a spherical vector using single precision +/// floats for the angles This is the fastest implementation on devices with +/// floating point harware using SphericalSingle = SphericalOf; +/// @brief Shorthand notation for a spherical vector using signed 16-bit words +/// for the angles +/// @note This is the fastest implementation on devices without floating point +/// hardware using Spherical16 = SphericalOf; } // namespace LinearAlgebra diff --git a/test/Spherical16_test.cc b/test/Spherical16_test.cc index 2e398e5..789a8c7 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical16_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Spherical.h" #include "Vector3.h" @@ -182,4 +182,41 @@ TEST(Spherical16, Addition) { EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 45) << "Addition(1 0 90)"; } +TEST(Spherical16, AdditionPerformance) { + const int numIterations = 1000000; // Number of additions to test + std::vector sphericalObjects; + + // Populate the vector with random SphericalOf objects + for (int i = 0; i < numIterations; ++i) { + float distance = (float)(rand() % 100); + float horizontal = (float)(rand() % 180); + float vertical = (float)(rand() % 360); + Spherical16 s = Spherical16::Deg(distance, horizontal, vertical); + sphericalObjects.push_back(s); + } + + // Measure the time to perform multiple additions + auto start = std::chrono::high_resolution_clock::now(); + + Spherical16 result = Spherical16::zero; // Start with a + // zero-initialized object + + for (int i = 0; i < numIterations - 1; ++i) { + result = result + sphericalObjects[i]; // Add objects + // together + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Time to perform " << numIterations - 1 + << " additions: " << duration.count() << " seconds." << std::endl; + + // Assert that the time taken is less than + // 1 second (or any other performance + // requirement) + ASSERT_LE(duration.count(), 1.0) << "Performance test failed: " + "Additions took longer than 1 " + "second."; +} + #endif \ No newline at end of file diff --git a/test/SphericalSingle_test.cc b/test/SphericalSingle_test.cc index 3e73e51..43f4151 100644 --- a/test/SphericalSingle_test.cc +++ b/test/SphericalSingle_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Spherical.h" @@ -173,4 +173,41 @@ TEST(SphericalSingle, Addition) { EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 45) << "Addition(1 0 90)"; } +TEST(SphericalSingle, AdditionPerformance) { + const int numIterations = 1000000; // Number of additions to test + std::vector sphericalObjects; + + // Populate the vector with random SphericalOf objects + for (int i = 0; i < numIterations; ++i) { + float distance = (float)(rand() % 100); + float horizontal = (float)(rand() % 180); + float vertical = (float)(rand() % 360); + SphericalSingle s = SphericalSingle::Deg(distance, horizontal, vertical); + sphericalObjects.push_back(s); + } + + // Measure the time to perform multiple additions + auto start = std::chrono::high_resolution_clock::now(); + + SphericalSingle result = SphericalSingle::zero; // Start with a + // zero-initialized object + + for (int i = 0; i < numIterations - 1; ++i) { + result = result + sphericalObjects[i]; // Add objects + // together + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Time to perform " << numIterations - 1 + << " additions: " << duration.count() << " seconds." << std::endl; + + // Assert that the time taken is less than + // 1 second (or any other performance + // requirement) + ASSERT_LE(duration.count(), 1.0) << "Performance test failed: " + "Additions took longer than 1 " + "second."; +} + #endif \ No newline at end of file From 58beb363ea523049955c207d15d4406a4ea8c6e5 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 27 Dec 2024 23:10:53 +0100 Subject: [PATCH 117/121] Completed AngleOf documentation --- Angle.cpp | 209 +++++++++++++++++++++------------------ Angle.h | 188 +++++++++++++++++++++++++++++------ FloatSingle.cpp | 2 + test/Angle16_test.cc | 10 +- test/Angle8_test.cc | 10 +- test/AngleSingle_test.cc | 4 +- test/FloatSingle_test.cc | 4 +- 7 files changed, 288 insertions(+), 139 deletions(-) diff --git a/Angle.cpp b/Angle.cpp index 6f27334..c88afdc 100644 --- a/Angle.cpp +++ b/Angle.cpp @@ -25,36 +25,34 @@ float Angle::Normalize(float angle) { template AngleOf::AngleOf() : value(0) {} -// template AngleOf::AngleOf(T angle) : value(angle) {} +template const AngleOf AngleOf::zero = AngleOf(); +// template +// const AngleOf AngleOf::deg90 = AngleOf::Degrees(90); +// template +// const AngleOf AngleOf::deg180 = AngleOf::Degrees(180); //===== AngleSingle, AngleOf -template <> AngleOf AngleOf::Degrees(float angle) { - if (isfinite(angle)) { - while (angle < -180) - angle += 360; - while (angle >= 180) - angle -= 360; +template <> AngleOf AngleOf::Degrees(float degrees) { + if (isfinite(degrees)) { + while (degrees < -180) + degrees += 360; + while (degrees >= 180) + degrees -= 360; } - return AngleOf(angle); + return Binary(degrees); } -template <> AngleOf AngleOf::Radians(float angle) { - if (isfinite(angle)) { - while (angle <= -pi) - angle += 2 * pi; - while (angle > pi) - angle -= 2 * pi; +template <> AngleOf AngleOf::Radians(float radians) { + if (isfinite(radians)) { + while (radians <= -pi) + radians += 2 * pi; + while (radians > pi) + radians -= 2 * pi; } - return AngleOf(angle * Rad2Deg); -} - -template AngleOf AngleOf::Binary(T x) { - AngleOf angle = AngleOf(); - angle.value = x; - return angle; + return Binary(radians * Rad2Deg); } template <> float AngleOf::InDegrees() const { return this->value; } @@ -65,19 +63,21 @@ template <> float AngleOf::InRadians() const { //===== Angle16, AngleOf -template <> AngleOf AngleOf::Degrees(float angle) { +template <> +AngleOf AngleOf::Degrees(float degrees) { // map float [-180..180) to integer [-32768..32767] - signed short value = (signed short)roundf(angle / 360.0F * 65536.0F); - return AngleOf(value); + signed short value = (signed short)roundf(degrees / 360.0F * 65536.0F); + return Binary(value); } -template <> AngleOf AngleOf::Radians(float angle) { - if (!isfinite(angle)) - return AngleOf(0); +template <> +AngleOf AngleOf::Radians(float radians) { + if (!isfinite(radians)) + return AngleOf::zero; // map float [-PI..PI) to integer [-32768..32767] - signed short value = (signed short)roundf(angle / pi * 32768.0F); - return AngleOf(value); + signed short value = (signed short)roundf(radians / pi * 32768.0F); + return Binary(value); } template <> float AngleOf::InDegrees() const { @@ -92,19 +92,19 @@ template <> float AngleOf::InRadians() const { //===== Angle8, AngleOf -template <> AngleOf AngleOf::Degrees(float angle) { +template <> AngleOf AngleOf::Degrees(float degrees) { // map float [-180..180) to integer [-128..127) - signed char value = (signed char)roundf(angle / 360.0F * 256.0F); - return AngleOf(value); + signed char value = (signed char)roundf(degrees / 360.0F * 256.0F); + return Binary(value); } -template <> AngleOf AngleOf::Radians(float angle) { - if (!isfinite(angle)) - return AngleOf(0); +template <> AngleOf AngleOf::Radians(float radians) { + if (!isfinite(radians)) + return AngleOf::zero; // map float [-pi..pi) to integer [-128..127) - signed char value = (signed char)roundf(angle / pi * 128.0f); - return AngleOf(value); + signed char value = (signed char)roundf(radians / pi * 128.0f); + return Binary(value); } template <> float AngleOf::InDegrees() const { @@ -119,90 +119,109 @@ template <> float AngleOf::InRadians() const { //===== Generic -// template -// const AngleOf AngleOf::zero = AngleOf(); -// template -// const AngleOf AngleOf::deg90 = AngleOf::Degrees(90); -// template -// const AngleOf AngleOf::deg180 = AngleOf::Degrees(180); - -template bool AngleOf::operator==(const AngleOf a) const { - return this->value == a.value; +template AngleOf AngleOf::Binary(T rawValue) { + AngleOf angle = AngleOf(); + angle.SetBinary(rawValue); + return angle; } -template bool AngleOf::operator>(AngleOf a) const { - return this->value > a.value; -} - -template bool AngleOf::operator>=(AngleOf a) const { - return this->value >= a.value; -} - -template bool AngleOf::operator<(AngleOf a) const { - return this->value < a.value; -} - -template bool AngleOf::operator<=(AngleOf a) const { - return this->value <= a.value; +template T AngleOf::GetBinary() const { return this->value; } +template void AngleOf::SetBinary(T rawValue) { + this->value = rawValue; } template -signed int Passer::LinearAlgebra::AngleOf::Sign(AngleOf a) { - if (a.value < 0) +bool AngleOf::operator==(const AngleOf angle) const { + return this->value == angle.value; +} + +template bool AngleOf::operator>(AngleOf angle) const { + return this->value > angle.value; +} + +template bool AngleOf::operator>=(AngleOf angle) const { + return this->value >= angle.value; +} + +template bool AngleOf::operator<(AngleOf angle) const { + return this->value < angle.value; +} + +template bool AngleOf::operator<=(AngleOf angle) const { + return this->value <= angle.value; +} + +template +signed int Passer::LinearAlgebra::AngleOf::Sign(AngleOf angle) { + if (angle.value < 0) return -1; - if (a.value > 0) + if (angle.value > 0) return 1; return 0; } template -AngleOf Passer::LinearAlgebra::AngleOf::Abs(AngleOf a) { - if (Sign(a) < 0) - return -a; +AngleOf Passer::LinearAlgebra::AngleOf::Abs(AngleOf angle) { + if (Sign(angle) < 0) + return -angle; else - return a; + return angle; } template AngleOf AngleOf::operator-() const { - AngleOf angle = AngleOf(-this->value); + AngleOf angle = Binary(-this->value); return angle; } template <> -AngleOf AngleOf::operator-(const AngleOf &a) const { - AngleOf angle = AngleOf(this->value - a.value); - angle = Normalize(angle); - return angle; +AngleOf AngleOf::operator-(const AngleOf &angle) const { + AngleOf r = Binary(this->value - angle.value); + r = Normalize(r); + return r; } template -AngleOf AngleOf::operator-(const AngleOf &a) const { - AngleOf angle = AngleOf(this->value - a.value); - return angle; +AngleOf AngleOf::operator-(const AngleOf &angle) const { + AngleOf r = Binary(this->value - angle.value); + return r; } template <> -AngleOf AngleOf::operator+(const AngleOf &a) const { - AngleOf angle = AngleOf(this->value + a.value); - angle = Normalize(angle); - return angle; +AngleOf AngleOf::operator+(const AngleOf &angle) const { + AngleOf r = Binary(this->value + angle.value); + r = Normalize(r); + return r; } template -AngleOf AngleOf::operator+(const AngleOf &a) const { - AngleOf angle = AngleOf(this->value + a.value); - return angle; +AngleOf AngleOf::operator+(const AngleOf &angle) const { + AngleOf r = Binary(this->value + angle.value); + return r; } -template <> AngleOf AngleOf::operator+=(const AngleOf &a) { - this->value += a.value; +template <> +AngleOf AngleOf::operator+=(const AngleOf &angle) { + this->value += angle.value; this->Normalize(); return *this; } -template AngleOf AngleOf::operator+=(const AngleOf &a) { - this->value += a.value; +template +AngleOf AngleOf::operator+=(const AngleOf &angle) { + this->value += angle.value; return *this; } +// This defintion is not matching the declaration in the header file somehow +// template +// AngleOf operator*(const AngleOf &angle, float factor) { +// return AngleOf::Degrees((float)angle.InDegrees() * factor); +// } + +// This defintion is not matching the declaration in the header file somehow +// template +// AngleOf operator*(float factor, const AngleOf &angle) { +// return AngleOf::Degrees((float)factor * angle.InDegrees()); +// } + template void AngleOf::Normalize() { float angleValue = this->InDegrees(); if (!isfinite(angleValue)) @@ -246,14 +265,14 @@ AngleOf AngleOf::MoveTowards(AngleOf fromAngle, AngleOf toAngle, return fromAngle + d; } -template float AngleOf::Cos(AngleOf a) { - return cosf(a.InRadians()); +template float AngleOf::Cos(AngleOf angle) { + return cosf(angle.InRadians()); } -template float AngleOf::Sin(AngleOf a) { - return sinf(a.InRadians()); +template float AngleOf::Sin(AngleOf angle) { + return sinf(angle.InRadians()); } -template float AngleOf::Tan(AngleOf a) { - return tanf(a.InRadians()); +template float AngleOf::Tan(AngleOf angle) { + return tanf(angle.InRadians()); } template AngleOf AngleOf::Acos(float f) { @@ -267,8 +286,8 @@ template AngleOf AngleOf::Atan(float f) { } template -AngleOf Passer::LinearAlgebra::AngleOf::Atan2(float f1, float f2) { - return AngleOf::Radians(atan2f(f1, f2)); +AngleOf Passer::LinearAlgebra::AngleOf::Atan2(float y, float x) { + return AngleOf::Radians(atan2f(y, x)); } // template <> @@ -353,4 +372,4 @@ AngleOf AngleOf::SineRuleAngle(float a, AngleOf beta, float b) { template class AngleOf; template class AngleOf; -template class AngleOf; +template class AngleOf; \ No newline at end of file diff --git a/Angle.h b/Angle.h index cd37350..1e4b445 100644 --- a/Angle.h +++ b/Angle.h @@ -13,77 +13,205 @@ static float pi = 3.1415927410125732421875F; static float Rad2Deg = 360.0f / (pi * 2); static float Deg2Rad = (pi * 2) / 360.0f; +/// @brief An angle in various representations. +/// @tparam T The internal type used for the representation of the angle. +/// The angle is internally limited to <-180..180] degrees or <-PI...PI] +/// radians. When an angle exceeds this range, it is normalized to a value +/// within the range. template class AngleOf { public: + /// @brief Create a new angle with a zero value AngleOf(); - static AngleOf Degrees(float f); - static AngleOf Radians(float f); - static AngleOf Binary(T x); - - // const static AngleOf zero; + /// @brief An zero value angle + const static AngleOf zero; // const static AngleOf deg90; // const static AngleOf deg180; + /// @brief Creates an angle in degrees + /// @param degrees the angle in degrees + /// @return The angle value + static AngleOf Degrees(float degrees); + /// @brief Short-hand Deg alias for the Degrees function + constexpr static auto Deg = Degrees; + /// @brief Creates an angle in radians + /// @param radians the angle in radians + /// @return The angle value + static AngleOf Radians(float radians); + /// @brief Short-hand Rad alias for the Radians function + constexpr static auto Rad = Radians; + /// @brief Creates an angle from a raw value + /// @param rawValue the raw value to use for the angle + /// @return The the angle + static AngleOf Binary(T rawValue); + + /// @brief Get the angle value in degrees + /// @return The angle value in degrees float InDegrees() const; + /// @brief Get the angle value in radians + /// @return The angle value in radians float InRadians() const; - inline T GetBinary() const { return this->value; } - inline void SetBinary(T x) { this->value = x; } + /// @brief Get the raw value for the angle + /// @return The raw value + T GetBinary() const; + /// @brief Set the raw value of the angle + /// @param rawValue The raw value + void SetBinary(T rawValue); - bool operator==(const AngleOf a) const; - bool operator>(AngleOf a) const; - bool operator>=(AngleOf a) const; - bool operator<(AngleOf a) const; - bool operator<=(AngleOf a) const; + /// @brief Tests whether this angle is equal to the given angle + /// @param angle The angle to compare to + /// @return True when the angles are equal, False otherwise + /// @note The equality is determine within the limits of precision of the raw + /// type T + bool operator==(const AngleOf angle) const; + /// @brief Tests if this angle is greater than the given angle + /// @param angle The given angle + /// @return True when this angle is greater than the given angle, False + /// otherwise + bool operator>(AngleOf angle) const; + /// @brief Tests if this angle is greater than or equal to the given angle + /// @param angle The given angle + /// @return True when this angle is greater than or equal to the given angle. + /// False otherwise. + bool operator>=(AngleOf angle) const; + /// @brief Tests if this angle is less than the given angle + /// @param angle The given angle + /// @return True when this angle is less than the given angle. False + /// otherwise. + bool operator<(AngleOf angle) const; + /// @brief Tests if this angle is less than or equal to the given angle + /// @param angle The given angle + /// @return True when this angle is less than or equal to the given angle. + /// False otherwise. + bool operator<=(AngleOf angle) const; - static signed int Sign(AngleOf a); - static AngleOf Abs(AngleOf a); + /// @brief Returns the sign of the angle + /// @param angle The angle + /// @return -1 when the angle is negative, 1 when it is positive and 0 + /// otherwise. + static signed int Sign(AngleOf angle); + /// @brief Returns the magnitude of the angle + /// @param angle The angle + /// @return The positive magitude of the angle. + /// Negative values are negated to get a positive result + static AngleOf Abs(AngleOf angle); + /// @brief Negate the angle + /// @return The negated angle AngleOf operator-() const; - AngleOf operator-(const AngleOf &a) const; - AngleOf operator+(const AngleOf &a) const; - AngleOf operator+=(const AngleOf &a); + /// @brief Substract another angle from this angle + /// @param angle The angle to subtract from this angle + /// @return The result of the subtraction + AngleOf operator-(const AngleOf &angle) const; + /// @brief Add another angle from this angle + /// @param angle The angle to add to this angle + /// @return The result of the addition + AngleOf operator+(const AngleOf &angle) const; + /// @brief Add another angle to this angle + /// @param angle The angle to add to this angle + /// @return The result of the addition + AngleOf operator+=(const AngleOf &angle); - friend AngleOf operator*(const AngleOf &a, float f) { - return AngleOf::Degrees((float)a.InDegrees() * f); + /// @brief Mutliplies the angle + /// @param angle The angle to multiply + /// @param factor The factor by which the angle is multiplied + /// @return The multiplied angle + friend AngleOf operator*(const AngleOf &angle, float factor) { + return AngleOf::Degrees((float)angle.InDegrees() * factor); } - friend AngleOf operator*(float f, const AngleOf &a) { - return AngleOf::Degrees((float)f * a.InDegrees()); + /// @brief Multiplies the angle + /// @param factor The factor by which the angle is multiplies + /// @param angle The angle to multiply + /// @return The multiplied angle + friend AngleOf operator*(float factor, const AngleOf &angle) { + return AngleOf::Degrees((float)factor * angle.InDegrees()); } + /// @brief Normalizes the angle to (-180..180] or (-PI..PI] + /// Should not be needed but available in case it is. void Normalize(); + /// @brief Normalizes the angle to (-180..180] or (-PI..PI] + /// @param angle The angle to normalize + /// @return The normalized angle; static AngleOf Normalize(AngleOf angle); - static AngleOf Clamp(AngleOf a, AngleOf min, AngleOf max); + /// @brief Clamps the angle value between the two given angles + /// @param angle The angle to clamp + /// @param min The minimum angle + /// @param max The maximum angle + /// @return The clamped value + /// @remark When the min value is greater than the max value, angle is + /// returned unclamped. + static AngleOf Clamp(AngleOf angle, AngleOf min, AngleOf max); // static AngleOf Difference(AngleOf a, AngleOf b) { // AngleOf r = Normalize(b.InDegrees() - a.InDegrees()); // return r; // }; + + /// @brief Rotates an angle towards another angle with a max distance + /// @param fromAngle The angle to start from + /// @param toAngle The angle to rotate towards + /// @param maxAngle The maximum angle to rotate + /// @return The rotated angle static AngleOf MoveTowards(AngleOf fromAngle, AngleOf toAngle, float maxAngle); - static float Cos(AngleOf a); - static float Sin(AngleOf a); - static float Tan(AngleOf a); + /// @brief Calculates the cosine of an angle + /// @param angle The given angle + /// @return The cosine of the angle + static float Cos(AngleOf angle); + /// @brief Calculates the sine of an angle + /// @param angle The given angle + /// @return The sine of the angle + static float Sin(AngleOf angle); + /// @brief Calculates the tangent of an angle + /// @param angle The given angle + /// @return The tangent of the angle + static float Tan(AngleOf angle); + /// @brief Calculates the arc cosine angle + /// @param f The value + /// @return The arc cosine for the given value static AngleOf Acos(float f); + /// @brief Calculates the arc sine angle + /// @param f The value + /// @return The arc sine for the given value static AngleOf Asin(float f); + /// @brief Calculates the arc tangent angle + /// @param f The value + /// @return The arc tangent for the given value static AngleOf Atan(float f); - static AngleOf Atan2(float f1, float f2); + /// @brief Calculates the tangent for the given values + /// @param y The vertical value + /// @param x The horizontal value + /// @return The tanget for the given values + /// Uses the y and x signs to compute the quadrant + static AngleOf Atan2(float y, float x); + /// @brief Computes the length of a side using the rule of cosines + /// @param a The length of side A + /// @param b The length of side B + /// @param gamma The angle of the corner opposing side C + /// @return The length of side C static float CosineRuleSide(float a, float b, AngleOf gamma); + /// @brief Computes the angle of a corner using the rule of cosines + /// @param a The length of side A + /// @param b The length of side B + /// @param c The length of side C + /// @return The angle of the corner opposing side C static AngleOf CosineRuleAngle(float a, float b, float c); + /// @brief Computes the angle of a corner using the rule of sines + /// @param a The length of side A + /// @param beta the angle of the corner opposing side B + /// @param c The length of side C + /// @return The angle of the corner opposing side A static AngleOf SineRuleAngle(float a, AngleOf beta, float c); private: T value; AngleOf(T value); - // These are deprecated, will move to private. - // Use Degrees/Radians instead - // AngleOf(signed int f); - // AngleOf(float f); }; using Angle = AngleOf; diff --git a/FloatSingle.cpp b/FloatSingle.cpp index a8c5db1..902d85e 100644 --- a/FloatSingle.cpp +++ b/FloatSingle.cpp @@ -9,6 +9,8 @@ const float Float::epsilon = 1e-05f; const float Float::sqrEpsilon = 1e-10f; float Float::Clamp(float f, float min, float max) { + if (max < min) + return f; if (f < min) return min; if (f > max) diff --git a/test/Angle16_test.cc b/test/Angle16_test.cc index 3f0fec2..16d8451 100644 --- a/test/Angle16_test.cc +++ b/test/Angle16_test.cc @@ -1,8 +1,8 @@ #if GTEST #include -#include #include +#include #include "Angle.h" @@ -86,7 +86,7 @@ TEST(Angle16, Normalize) { r = Angle16::Normalize(Angle16::Degrees(0)); EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Normalize 0"; - if (false) { // std::numeric_limits::is_iec559) { + if (false) { // std::numeric_limits::is_iec559) { // Infinites are not supported r = Angle16::Normalize(Angle16::Degrees(FLOAT_INFINITY)); EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "Normalize INFINITY"; @@ -123,9 +123,9 @@ TEST(Angle16, Clamp) { r = Angle16::Clamp(Angle16::Degrees(0), Angle16::Degrees(10), Angle16::Degrees(-10)); - EXPECT_NEAR(r.InDegrees(), 10, 1.0e-2) << "Clamp 0 10 -10"; + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 10 -10"; - if (false) { // std::numeric_limits::is_iec559) { + if (false) { // std::numeric_limits::is_iec559) { // Infinites are not supported r = Angle16::Clamp(Angle16::Degrees(10), Angle16::Degrees(0), Angle16::Degrees(FLOAT_INFINITY)); @@ -216,7 +216,7 @@ TEST(Angle16, MoveTowards) { r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(0), 30); EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 30"; - if (false) { // std::numeric_limits::is_iec559) { + if (false) { // std::numeric_limits::is_iec559) { // infinites are not supported r = Angle16::MoveTowards(Angle16::Degrees(0), Angle16::Degrees(90), FLOAT_INFINITY); diff --git a/test/Angle8_test.cc b/test/Angle8_test.cc index bb220c5..158694f 100644 --- a/test/Angle8_test.cc +++ b/test/Angle8_test.cc @@ -1,8 +1,8 @@ #if GTEST #include -#include #include +#include #include "Angle.h" @@ -86,7 +86,7 @@ TEST(Angle8, Normalize) { r = Angle8::Normalize(Angle8::Degrees(0)); EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Normalize 0"; - if (false) { // std::numeric_limits::is_iec559) { + if (false) { // std::numeric_limits::is_iec559) { // Infinites are not supported r = Angle8::Normalize(Angle8::Degrees(FLOAT_INFINITY)); EXPECT_FLOAT_EQ(r.InDegrees(), FLOAT_INFINITY) << "Normalize INFINITY"; @@ -122,9 +122,9 @@ TEST(Angle8, Clamp) { r = Angle8::Clamp(Angle8::Degrees(0), Angle8::Degrees(10), Angle8::Degrees(-10)); - EXPECT_NEAR(r.InDegrees(), 10, 1.0e-0) << "Clamp 0 10 -10"; + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 10 -10"; - if (false) { // std::numeric_limits::is_iec559) { + if (false) { // std::numeric_limits::is_iec559) { // Infinites are not supported r = Angle8::Clamp(Angle8::Degrees(10), Angle8::Degrees(0), Angle8::Degrees(FLOAT_INFINITY)); @@ -215,7 +215,7 @@ TEST(Angle8, MoveTowards) { r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(0), 30); EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "MoveTowards 0 0 30"; - if (false) { // std::numeric_limits::is_iec559) { + if (false) { // std::numeric_limits::is_iec559) { // infinites are not supported r = Angle8::MoveTowards(Angle8::Degrees(0), Angle8::Degrees(90), FLOAT_INFINITY); diff --git a/test/AngleSingle_test.cc b/test/AngleSingle_test.cc index cc0774e..9537ffb 100644 --- a/test/AngleSingle_test.cc +++ b/test/AngleSingle_test.cc @@ -1,8 +1,8 @@ #if GTEST #include -#include #include +#include #include "Angle.h" @@ -120,7 +120,7 @@ TEST(AngleSingle, Clamp) { r = AngleSingle::Clamp(AngleSingle::Degrees(0), AngleSingle::Degrees(1), AngleSingle::Degrees(-1)); - EXPECT_FLOAT_EQ(r.InDegrees(), 1) << "Clamp 0 1 -1"; + EXPECT_FLOAT_EQ(r.InDegrees(), 0) << "Clamp 0 1 -1"; if (std::numeric_limits::is_iec559) { r = AngleSingle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), diff --git a/test/FloatSingle_test.cc b/test/FloatSingle_test.cc index 58e9d6d..9673ade 100644 --- a/test/FloatSingle_test.cc +++ b/test/FloatSingle_test.cc @@ -1,8 +1,8 @@ #if GTEST #include -#include #include +#include #include "FloatSingle.h" @@ -27,7 +27,7 @@ TEST(FloatC, Clamp) { EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 0 0"; r = Float::Clamp(0, 1, -1); - EXPECT_FLOAT_EQ(r, 1) << "Clamp 0 1 -1"; + EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 1 -1"; if (std::numeric_limits::is_iec559) { r = Float::Clamp(1, 0, FLOAT_INFINITY); From 64b7f1103b6bbb31a0a5726b47da933c4251cda2 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 27 Dec 2024 23:18:39 +0100 Subject: [PATCH 118/121] Removed default Angle type --- Angle.h | 2 +- DoxyGen/DoxyWarnLogfile.txt | 14 +++++----- Polar.cpp | 51 ++++++++++++++---------------------- Spherical.cpp | 4 +-- Vector2.cpp | 51 ++++++++++++++++-------------------- Vector2.h | 47 ++++++++++++++++----------------- test/AngleSingle_test.cc | 6 ++--- test/Polar_test.cc | 50 +++++++++++++++++------------------ test/SphericalSingle_test.cc | 28 ++++++++++---------- test/Vector2_test.cc | 10 +++---- 10 files changed, 122 insertions(+), 141 deletions(-) diff --git a/Angle.h b/Angle.h index 1e4b445..27aac41 100644 --- a/Angle.h +++ b/Angle.h @@ -214,7 +214,7 @@ private: AngleOf(T value); }; -using Angle = AngleOf; +// using Angle = AngleOf; using AngleSingle = AngleOf; using Angle16 = AngleOf; using Angle8 = AngleOf; diff --git a/DoxyGen/DoxyWarnLogfile.txt b/DoxyGen/DoxyWarnLogfile.txt index 2e253db..b1425a0 100644 --- a/DoxyGen/DoxyWarnLogfile.txt +++ b/DoxyGen/DoxyWarnLogfile.txt @@ -2,8 +2,8 @@ warning: source 'images' is not a readable file or directory... skipping. d:/PlatformIO/linear-algebra/Quaternion.cpp:100: warning: no uniquely matching class member found for Quaternion Quaternion::operator*(const Quaternion &r2) const Possible candidates: - 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(const AngleOf< T > &a, float f)' at line 48 of file d:/PlatformIO/linear-algebra/Angle.h - 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(float f, const AngleOf< T > &a)' at line 51 of file d:/PlatformIO/linear-algebra/Angle.h + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(const AngleOf< T > &angle, float factor)' at line 120 of file d:/PlatformIO/linear-algebra/Angle.h + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(float factor, const AngleOf< T > &angle)' at line 127 of file d:/PlatformIO/linear-algebra/Angle.h 'Vector3 Passer::LinearAlgebra::MatrixOf< T >::operator*(const Vector3 v) const' at line 64 of file d:/PlatformIO/linear-algebra/Matrix.h 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(const PolarOf &v, float f)' at line 100 of file d:/PlatformIO/linear-algebra/Polar.h 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(float f, const PolarOf &v)' at line 103 of file d:/PlatformIO/linear-algebra/Polar.h @@ -20,8 +20,8 @@ Possible candidates: d:/PlatformIO/linear-algebra/Quaternion.cpp:108: warning: no uniquely matching class member found for Vector3 Quaternion::operator*(const Vector3 &p) const Possible candidates: - 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(const AngleOf< T > &a, float f)' at line 48 of file d:/PlatformIO/linear-algebra/Angle.h - 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(float f, const AngleOf< T > &a)' at line 51 of file d:/PlatformIO/linear-algebra/Angle.h + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(const AngleOf< T > &angle, float factor)' at line 120 of file d:/PlatformIO/linear-algebra/Angle.h + 'friend AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator*(float factor, const AngleOf< T > &angle)' at line 127 of file d:/PlatformIO/linear-algebra/Angle.h 'Vector3 Passer::LinearAlgebra::MatrixOf< T >::operator*(const Vector3 v) const' at line 64 of file d:/PlatformIO/linear-algebra/Matrix.h 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(const PolarOf &v, float f)' at line 100 of file d:/PlatformIO/linear-algebra/Polar.h 'friend PolarOf Passer::LinearAlgebra::PolarOf< T >::operator*(float f, const PolarOf &v)' at line 103 of file d:/PlatformIO/linear-algebra/Polar.h @@ -54,8 +54,8 @@ d:/PlatformIO/linear-algebra/Spherical.cpp:137: warning: no uniquely matching cl template < T > SphericalOf< T > SphericalOf::operator-(const SphericalOf< T > &s2) const Possible candidates: - 'AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator-() const' at line 43 of file d:/PlatformIO/linear-algebra/Angle.h - 'AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator-(const AngleOf< T > &a) const' at line 44 of file d:/PlatformIO/linear-algebra/Angle.h + 'AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator-() const' at line 102 of file d:/PlatformIO/linear-algebra/Angle.h + 'AngleOf< T > Passer::LinearAlgebra::AngleOf< T >::operator-(const AngleOf< T > &angle) const' at line 106 of file d:/PlatformIO/linear-algebra/Angle.h 'DirectionOf< T > Passer::LinearAlgebra::DirectionOf< T >::operator-() const' at line 41 of file d:/PlatformIO/linear-algebra/Direction.h 'PolarOf Passer::LinearAlgebra::PolarOf< T >::operator-() const' at line 82 of file d:/PlatformIO/linear-algebra/Polar.h 'PolarOf Passer::LinearAlgebra::PolarOf< T >::operator-(const PolarOf &v) const' at line 87 of file d:/PlatformIO/linear-algebra/Polar.h @@ -118,3 +118,5 @@ d:/PlatformIO/linear-algebra/Vector3.h:158: warning: Member operator*=(float f) d:/PlatformIO/linear-algebra/Vector3.h:170: warning: Member operator/=(float f) (function) of struct Passer::LinearAlgebra::Vector3 is not documented. d:/PlatformIO/linear-algebra/Vector3.h:154: warning: Member operator*(float f, const Vector3 &v) (friend) of struct Passer::LinearAlgebra::Vector3 is not documented. d:/PlatformIO/linear-algebra/Vector3.h:166: warning: Member operator/(float f, const Vector3 &v) (friend) of struct Passer::LinearAlgebra::Vector3 is not documented. +t f, const Vector3 &v) (friend) of struct Passer::LinearAlgebra::Vector3 is not documented. +d:/PlatformIO/linear-algebra/Vector3.h:166: warning: Member operator/(float f, const Vector3 &v) (friend) of struct Passer::LinearAlgebra::Vector3 is not documented. diff --git a/Polar.cpp b/Polar.cpp index 35d1576..92f4ba0 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -2,13 +2,11 @@ #include "Polar.h" -template -PolarOf::PolarOf() { +template PolarOf::PolarOf() { this->distance = 0.0f; this->angle = AngleOf(); } -template -PolarOf::PolarOf(float distance, AngleOf angle) { +template PolarOf::PolarOf(float distance, AngleOf angle) { // distance should always be 0 or greater if (distance < 0.0f) { this->distance = -distance; @@ -23,16 +21,14 @@ PolarOf::PolarOf(float distance, AngleOf angle) { } } -template -PolarOf PolarOf::FromVector2(Vector2 v) { +template PolarOf PolarOf::FromVector2(Vector2 v) { float distance = v.magnitude(); AngleOf angle = AngleOf::Degrees(Vector2::SignedAngle(Vector2::forward, v)); PolarOf p = PolarOf(distance, angle); return p; } -template -PolarOf PolarOf::FromSpherical(SphericalOf v) { +template PolarOf PolarOf::FromSpherical(SphericalOf v) { float distance = v.distance * cosf(v.direction.vertical.InDegrees() * Passer::LinearAlgebra::Deg2Rad); AngleOf angle = v.direction.horizontal; @@ -51,43 +47,36 @@ const PolarOf PolarOf::right = PolarOf(1.0, AngleOf::Degrees(90)); template const PolarOf PolarOf::left = PolarOf(1.0, AngleOf::Degrees(-90)); -template -bool PolarOf::operator==(const PolarOf& v) const { +template bool PolarOf::operator==(const PolarOf &v) const { return (this->distance == v.distance && this->angle.InDegrees() == v.angle.InDegrees()); } -template -PolarOf PolarOf::Normalize(const PolarOf& v) { +template PolarOf PolarOf::Normalize(const PolarOf &v) { PolarOf r = PolarOf(1, v.angle); return r; } -template -PolarOf PolarOf::normalized() const { +template PolarOf PolarOf::normalized() const { PolarOf r = PolarOf(1, this->angle); return r; } -template -PolarOf PolarOf::operator-() const { +template PolarOf PolarOf::operator-() const { PolarOf v = PolarOf(this->distance, this->angle + AngleOf::Degrees(180)); return v; } -template -PolarOf PolarOf::operator-(const PolarOf& v) const { +template PolarOf PolarOf::operator-(const PolarOf &v) const { PolarOf r = -v; return *this + r; } -template -PolarOf PolarOf::operator-=(const PolarOf& v) { +template PolarOf PolarOf::operator-=(const PolarOf &v) { *this = *this - v; return *this; } -template -PolarOf PolarOf::operator+(const PolarOf& v) const { +template PolarOf PolarOf::operator+(const PolarOf &v) const { if (v.distance == 0) return PolarOf(this->distance, this->angle); if (this->distance == 0.0f) @@ -105,8 +94,9 @@ PolarOf PolarOf::operator+(const PolarOf& v) const { float newDistance = AngleOf::CosineRuleSide(v.distance, this->distance, AngleOf::Degrees(rotation)); - float angle = Angle::CosineRuleAngle(newDistance, this->distance, v.distance) - .InDegrees(); + float angle = + AngleSingle::CosineRuleAngle(newDistance, this->distance, v.distance) + .InDegrees(); float newAngle = deltaAngle < 0.0f ? this->angle.InDegrees() - angle : this->angle.InDegrees() + angle; @@ -114,32 +104,29 @@ PolarOf PolarOf::operator+(const PolarOf& v) const { PolarOf vector = PolarOf(newDistance, newAngleA); return vector; } -template -PolarOf PolarOf::operator+=(const PolarOf& v) { +template PolarOf PolarOf::operator+=(const PolarOf &v) { *this = *this + v; return *this; } -template -PolarOf PolarOf::operator*=(float f) { +template PolarOf PolarOf::operator*=(float f) { this->distance *= f; return *this; } -template -PolarOf PolarOf::operator/=(float f) { +template PolarOf PolarOf::operator/=(float f) { this->distance /= f; return *this; } template -float PolarOf::Distance(const PolarOf& v1, const PolarOf& v2) { +float PolarOf::Distance(const PolarOf &v1, const PolarOf &v2) { float d = AngleOf::CosineRuleSide(v1.distance, v2.distance, v2.angle - v1.angle); return d; } template -PolarOf PolarOf::Rotate(const PolarOf& v, AngleOf angle) { +PolarOf PolarOf::Rotate(const PolarOf &v, AngleOf angle) { AngleOf a = AngleOf::Normalize(v.angle + angle); PolarOf r = PolarOf(v.distance, a); return r; diff --git a/Spherical.cpp b/Spherical.cpp index cde7654..e82c9af 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -251,7 +251,7 @@ AngleOf SphericalOf::AngleBetween(const SphericalOf &v1, // float cdot = Float::Clamp(fraction, -1.0, 1.0); // float r = ((float)acos(cdot)) * Rad2Deg; - Angle r = Vector3::Angle(v1_3, v2_3); + AngleSingle r = Vector3::Angle(v1_3, v2_3); return AngleOf::Degrees(r.InDegrees()); } @@ -262,7 +262,7 @@ AngleOf Passer::LinearAlgebra::SphericalOf::SignedAngleBetween( Vector3 v1_vector = v1.ToVector3(); Vector3 v2_vector = v2.ToVector3(); Vector3 axis_vector = axis.ToVector3(); - Angle r = Vector3::SignedAngle(v1_vector, v2_vector, axis_vector); + AngleSingle r = Vector3::SignedAngle(v1_vector, v2_vector, axis_vector); return AngleOf::Degrees(r.InDegrees()); } diff --git a/Vector2.cpp b/Vector2.cpp index 01c72e9..e895992 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -26,8 +26,8 @@ Vector2::Vector2(float _x, float _y) { // y = v.y; // } Vector2::Vector2(Vector3 v) { - x = v.Right(); // x; - y = v.Forward(); // z; + x = v.Right(); // x; + y = v.Forward(); // z; } Vector2::Vector2(Polar p) { float horizontalRad = p.angle.InDegrees() * Passer::LinearAlgebra::Deg2Rad; @@ -49,24 +49,18 @@ const Vector2 Vector2::down = Vector2(0, -1); const Vector2 Vector2::forward = Vector2(0, 1); const Vector2 Vector2::back = Vector2(0, -1); -bool Vector2::operator==(const Vector2& v) { +bool Vector2::operator==(const Vector2 &v) { return (this->x == v.x && this->y == v.y); } -float Vector2::Magnitude(const Vector2& v) { +float Vector2::Magnitude(const Vector2 &v) { return sqrtf(v.x * v.x + v.y * v.y); } -float Vector2::magnitude() const { - return (float)sqrtf(x * x + y * y); -} -float Vector2::SqrMagnitude(const Vector2& v) { - return v.x * v.x + v.y * v.y; -} -float Vector2::sqrMagnitude() const { - return (x * x + y * y); -} +float Vector2::magnitude() const { return (float)sqrtf(x * x + y * y); } +float Vector2::SqrMagnitude(const Vector2 &v) { return v.x * v.x + v.y * v.y; } +float Vector2::sqrMagnitude() const { return (x * x + y * y); } -Vector2 Vector2::Normalize(const Vector2& v) { +Vector2 Vector2::Normalize(const Vector2 &v) { float num = Vector2::Magnitude(v); Vector2 result = Vector2::zero; if (num > Float::epsilon) { @@ -83,28 +77,26 @@ Vector2 Vector2::normalized() const { return result; } -Vector2 Vector2::operator-() { - return Vector2(-this->x, -this->y); -} +Vector2 Vector2::operator-() { return Vector2(-this->x, -this->y); } -Vector2 Vector2::operator-(const Vector2& v) const { +Vector2 Vector2::operator-(const Vector2 &v) const { return Vector2(this->x - v.x, this->y - v.y); } -Vector2 Vector2::operator-=(const Vector2& v) { +Vector2 Vector2::operator-=(const Vector2 &v) { this->x -= v.x; this->y -= v.y; return *this; } -Vector2 Vector2::operator+(const Vector2& v) const { +Vector2 Vector2::operator+(const Vector2 &v) const { return Vector2(this->x + v.x, this->y + v.y); } -Vector2 Vector2::operator+=(const Vector2& v) { +Vector2 Vector2::operator+=(const Vector2 &v) { this->x += v.x; this->y += v.y; return *this; } -Vector2 Vector2::Scale(const Vector2& v1, const Vector2& v2) { +Vector2 Vector2::Scale(const Vector2 &v1, const Vector2 &v2) { return Vector2(v1.x * v2.x, v1.y * v2.y); } // Vector2 Passer::LinearAlgebra::operator*(const Vector2 &v, float f) { @@ -130,18 +122,18 @@ Vector2 Vector2::operator/=(float f) { return *this; } -float Vector2::Dot(const Vector2& v1, const Vector2& v2) { +float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) { return v1.x * v2.x + v1.y * v2.y; } -float Vector2::Distance(const Vector2& v1, const Vector2& v2) { +float Vector2::Distance(const Vector2 &v1, const Vector2 &v2) { return Magnitude(v1 - v2); } -float Vector2::Angle(const Vector2& v1, const Vector2& v2) { +float Vector2::Angle(const Vector2 &v1, const Vector2 &v2) { return (float)fabs(SignedAngle(v1, v2)); } -float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) { +float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { float sqrMagFrom = v1.sqrMagnitude(); float sqrMagTo = v2.sqrMagnitude(); @@ -159,11 +151,12 @@ float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) { return -(angleTo - angleFrom) * Passer::LinearAlgebra::Rad2Deg; } -Vector2 Vector2::Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a) { +Vector2 Vector2::Rotate(const Vector2 &v, + Passer::LinearAlgebra::AngleSingle a) { float angleRad = a.InDegrees() * Passer::LinearAlgebra::Deg2Rad; #if defined(AVR) float sinValue = sin(angleRad); - float cosValue = cos(angleRad); // * Angle::Deg2Rad); + float cosValue = cos(angleRad); // * Angle::Deg2Rad); #else float sinValue = (float)sinf(angleRad); float cosValue = (float)cosf(angleRad); @@ -176,7 +169,7 @@ Vector2 Vector2::Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a) { return r; } -Vector2 Vector2::Lerp(const Vector2& v1, const Vector2& v2, float f) { +Vector2 Vector2::Lerp(const Vector2 &v1, const Vector2 &v2, float f) { Vector2 v = v1 + (v2 - v1) * f; return v; } diff --git a/Vector2.h b/Vector2.h index 7805e69..eabac98 100644 --- a/Vector2.h +++ b/Vector2.h @@ -30,8 +30,7 @@ namespace Passer { namespace LinearAlgebra { struct Vector3; -template -class PolarOf; +template class PolarOf; // using Polar = PolarOf /// @brief A 2=dimensional vector @@ -40,7 +39,7 @@ class PolarOf; struct Vector2 : Vec2 { friend struct Vec2; - public: +public: /// @brief A new 2-dimensional zero vector Vector2(); /// @brief A new 2-dimensional vector @@ -82,12 +81,12 @@ struct Vector2 : Vec2 { /// @return true if it is identical to the given vector /// @note This uses float comparison to check equality which may have strange /// effects. Equality on floats should be avoided. - bool operator==(const Vector2& v); + bool operator==(const Vector2 &v); /// @brief The vector length /// @param v The vector for which you need the length /// @return The vector length - static float Magnitude(const Vector2& v); + static float Magnitude(const Vector2 &v); /// @brief The vector length /// @return The vector length float magnitude() const; @@ -97,7 +96,7 @@ struct Vector2 : Vec2 { /// @remark The squared length is computationally simpler than the real /// length. Think of Pythagoras A^2 + B^2 = C^2. This prevents the calculation /// of the squared root of C. - static float SqrMagnitude(const Vector2& v); + static float SqrMagnitude(const Vector2 &v); /// @brief The squared vector length /// @return The squared vector length /// @remark The squared length is computationally simpler than the real @@ -108,7 +107,7 @@ struct Vector2 : Vec2 { /// @brief Convert the vector to a length of 1 /// @param v The vector to convert /// @return The vector normalized to a length of 1 - static Vector2 Normalize(const Vector2& v); + static Vector2 Normalize(const Vector2 &v); /// @brief Convert the vector to a length 1 /// @return The vector normalized to a length of 1 Vector2 normalized() const; @@ -120,13 +119,13 @@ struct Vector2 : Vec2 { /// @brief Subtract a vector from this vector /// @param v The vector to subtract from this vector /// @return The result of the subtraction - Vector2 operator-(const Vector2& v) const; - Vector2 operator-=(const Vector2& v); + Vector2 operator-(const Vector2 &v) const; + Vector2 operator-=(const Vector2 &v); /// @brief Add a vector to this vector /// @param v The vector to add to this vector /// @return The result of the addition - Vector2 operator+(const Vector2& v) const; - Vector2 operator+=(const Vector2& v); + Vector2 operator+(const Vector2 &v) const; + Vector2 operator+=(const Vector2 &v); /// @brief Scale the vector using another vector /// @param v1 The vector to scale @@ -134,16 +133,16 @@ struct Vector2 : Vec2 { /// @return The scaled vector /// @remark Each component of the vector v1 will be multiplied with the /// matching component from the scaling vector v2. - static Vector2 Scale(const Vector2& v1, const Vector2& v2); + static Vector2 Scale(const Vector2 &v1, const Vector2 &v2); /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - friend Vector2 operator*(const Vector2& v, float f) { + friend Vector2 operator*(const Vector2 &v, float f) { return Vector2(v.x * f, v.y * f); } - friend Vector2 operator*(float f, const Vector2& v) { + friend Vector2 operator*(float f, const Vector2 &v) { return Vector2(v.x * f, v.y * f); // return Vector2(f * v.x, f * v.y); } @@ -152,10 +151,10 @@ struct Vector2 : Vec2 { /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - friend Vector2 operator/(const Vector2& v, float f) { + friend Vector2 operator/(const Vector2 &v, float f) { return Vector2(v.x / f, v.y / f); } - friend Vector2 operator/(float f, const Vector2& v) { + friend Vector2 operator/(float f, const Vector2 &v) { return Vector2(f / v.x, f / v.y); } Vector2 operator/=(float f); @@ -164,13 +163,13 @@ struct Vector2 : Vec2 { /// @param v1 The first vector /// @param v2 The second vector /// @return The dot product of the two vectors - static float Dot(const Vector2& v1, const Vector2& v2); + static float Dot(const Vector2 &v1, const Vector2 &v2); /// @brief The distance between two vectors /// @param v1 The first vector /// @param v2 The second vector /// @return The distance between the two vectors - static float Distance(const Vector2& v1, const Vector2& v2); + static float Distance(const Vector2 &v1, const Vector2 &v2); /// @brief The angle between two vectors /// @param v1 The first vector @@ -179,18 +178,18 @@ struct Vector2 : Vec2 { /// @remark This reterns an unsigned angle which is the shortest distance /// between the two vectors. Use Vector2::SignedAngle if a signed angle is /// needed. - static float Angle(const Vector2& v1, const Vector2& v2); + static float Angle(const Vector2 &v1, const Vector2 &v2); /// @brief The signed angle between two vectors /// @param v1 The starting vector /// @param v2 The ending vector /// @return The signed angle between the two vectors - static float SignedAngle(const Vector2& v1, const Vector2& v2); + static float SignedAngle(const Vector2 &v1, const Vector2 &v2); /// @brief Rotate the vector /// @param v The vector to rotate /// @param a The angle in degrees to rotate /// @return The rotated vector - static Vector2 Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a); + static Vector2 Rotate(const Vector2 &v, Passer::LinearAlgebra::AngleSingle a); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector @@ -200,11 +199,11 @@ struct Vector2 : Vec2 { /// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value /// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference /// between *v1* and *v2* etc. - static Vector2 Lerp(const Vector2& v1, const Vector2& v2, float f); + static Vector2 Lerp(const Vector2 &v1, const Vector2 &v2, float f); }; -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #include "Polar.h" diff --git a/test/AngleSingle_test.cc b/test/AngleSingle_test.cc index 9537ffb..773dfe4 100644 --- a/test/AngleSingle_test.cc +++ b/test/AngleSingle_test.cc @@ -63,7 +63,7 @@ TEST(AngleSingle, Compare) { } TEST(AngleSingle, Normalize) { - Angle r = AngleSingle(); + AngleSingle r = AngleSingle(); r = AngleSingle::Normalize(AngleSingle::Degrees(90.0f)); EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Normalize 90"; @@ -96,7 +96,7 @@ TEST(AngleSingle, Normalize) { } TEST(AngleSingle, Clamp) { - Angle r = AngleSingle(); + AngleSingle r = AngleSingle(); r = AngleSingle::Clamp(AngleSingle::Degrees(1), AngleSingle::Degrees(0), AngleSingle::Degrees(2)); @@ -135,7 +135,7 @@ TEST(AngleSingle, Clamp) { } // TEST(AngleSingle, Difference) { -// Angle r = 0; +// AngleSingle r = 0; // r = AngleSingle::Difference(0, 90); // EXPECT_FLOAT_EQ(r.InDegrees(), 90) << "Difference 0 90"; diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 8bfd55f..7f93074 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -32,40 +32,40 @@ TEST(Polar, FromSpherical) { SphericalSingle s; Polar p; - s = SphericalSingle(1, Angle::Degrees(0), Angle::Degrees(0)); + s = SphericalSingle(1, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(1 0 0)"; - s = SphericalSingle(1, Angle::Degrees(45), Angle::Degrees(0)); + s = SphericalSingle(1, AngleSingle::Degrees(45), AngleSingle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 45.0F) << "p.angle FromSpherical(1 45 0)"; - s = SphericalSingle(1, Angle::Degrees(-45), Angle::Degrees(0)); + s = SphericalSingle(1, AngleSingle::Degrees(-45), AngleSingle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -45.0F) << "p.angle FromSpherical(1 -45 0)"; - s = SphericalSingle(0, Angle::Degrees(0), Angle::Degrees(0)); + s = SphericalSingle(0, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 0)"; - s = SphericalSingle(-1, Angle::Degrees(0), Angle::Degrees(0)); + s = SphericalSingle(-1, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -180.0F) << "p.angle FromSpherical(-1 0 0)"; - s = SphericalSingle(0, Angle::Degrees(0), Angle::Degrees(90)); + s = SphericalSingle(0, AngleSingle::Degrees(0), AngleSingle::Degrees(90)); p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)"; @@ -73,32 +73,32 @@ TEST(Polar, FromSpherical) { } TEST(Polar, Negation) { - Polar v = Polar(2, Angle::Degrees(45)); + Polar v = Polar(2, AngleSingle::Degrees(45)); Polar r = Polar::zero; r = -v; EXPECT_FLOAT_EQ(r.distance, 2); EXPECT_FLOAT_EQ(r.angle.InDegrees(), -135); - EXPECT_TRUE(r == Polar(2, Angle::Degrees(-135))) << "Negate(2 45)"; + EXPECT_TRUE(r == Polar(2, AngleSingle::Degrees(-135))) << "Negate(2 45)"; - v = Polar(2, Angle::Degrees(-45)); + v = Polar(2, AngleSingle::Degrees(-45)); r = -v; - EXPECT_TRUE(r == Polar(2, Angle::Degrees(135))) << "Negate(2 -45)"; + EXPECT_TRUE(r == Polar(2, AngleSingle::Degrees(135))) << "Negate(2 -45)"; - v = Polar(2, Angle::Degrees(0)); + v = Polar(2, AngleSingle::Degrees(0)); r = -v; - EXPECT_TRUE(r == Polar(2, Angle::Degrees(180))) << "Negate(2 0)"; + EXPECT_TRUE(r == Polar(2, AngleSingle::Degrees(180))) << "Negate(2 0)"; - v = Polar(0, Angle::Degrees(0)); + v = Polar(0, AngleSingle::Degrees(0)); r = -v; EXPECT_FLOAT_EQ(r.distance, 0.0f); EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0.0f); - EXPECT_TRUE(r == Polar(0, Angle::Degrees(0))) << "Negate(0 0)"; + EXPECT_TRUE(r == Polar(0, AngleSingle::Degrees(0))) << "Negate(0 0)"; } TEST(Polar, Subtraction) { - Polar v1 = Polar(4, Angle::Degrees(45)); - Polar v2 = Polar(1, Angle::Degrees(-90)); + Polar v1 = Polar(4, AngleSingle::Degrees(45)); + Polar v2 = Polar(1, AngleSingle::Degrees(-90)); Polar r = Polar::zero; r = v1 - v2; @@ -110,8 +110,8 @@ TEST(Polar, Subtraction) { } TEST(Polar, Addition) { - Polar v1 = Polar(1, Angle::Degrees(45)); - Polar v2 = Polar(1, Angle::Degrees(-90)); + Polar v1 = Polar(1, AngleSingle::Degrees(45)); + Polar v2 = Polar(1, AngleSingle::Degrees(-90)); Polar r = Polar::zero; r = v1 - v2; @@ -125,14 +125,14 @@ TEST(Polar, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; - v2 = Polar(1, Angle::Degrees(-45)); + v2 = Polar(1, AngleSingle::Degrees(-45)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0) << "Addition(0 0 0)"; } TEST(Polar, Scale_Multiply) { - Polar v1 = Polar(4, Angle::Degrees(45)); + Polar v1 = Polar(4, AngleSingle::Degrees(45)); Polar r = Polar::zero; r = v1 * 2.0f; @@ -142,7 +142,7 @@ TEST(Polar, Scale_Multiply) { } TEST(Polar, Scale_Divide) { - Polar v1 = Polar(4, Angle::Degrees(45)); + Polar v1 = Polar(4, AngleSingle::Degrees(45)); Polar r = Polar::zero; r = v1 / 2.0f; @@ -152,8 +152,8 @@ TEST(Polar, Scale_Divide) { } TEST(Polar, Distance) { - Polar v1 = Polar(4, Angle::Degrees(45)); - Polar v2 = Polar(1, Angle::Degrees(-90)); + Polar v1 = Polar(4, AngleSingle::Degrees(45)); + Polar v2 = Polar(1, AngleSingle::Degrees(-90)); float d = 0; d = Polar::Distance(v1, v2); @@ -165,10 +165,10 @@ TEST(Polar, Distance) { } TEST(Polar, Rotate) { - Polar v = Polar(4, Angle::Degrees(45)); + Polar v = Polar(4, AngleSingle::Degrees(45)); Polar r = Polar::zero; - r = Polar::Rotate(v, Angle::Degrees(45)); + r = Polar::Rotate(v, AngleSingle::Degrees(45)); EXPECT_FLOAT_EQ(r.distance, v.distance) << "Rotate(4 45, 45)"; EXPECT_FLOAT_EQ(r.angle.InDegrees(), 90.0f) << "Rotate(4 45, 45)"; } diff --git a/test/SphericalSingle_test.cc b/test/SphericalSingle_test.cc index 43f4151..e77276a 100644 --- a/test/SphericalSingle_test.cc +++ b/test/SphericalSingle_test.cc @@ -31,7 +31,7 @@ TEST(SphericalSingle, FromVector3) { } TEST(SphericalSingle, FromPolar) { - Polar p = Polar(1, Angle::Degrees(0)); + Polar p = Polar(1, AngleSingle::Degrees(0)); SphericalSingle s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; @@ -40,7 +40,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 0)"; - p = Polar(1, Angle::Degrees(45)); + p = Polar(1, AngleSingle::Degrees(45)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; @@ -49,7 +49,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 45)"; - p = Polar(1, Angle::Degrees(-45)); + p = Polar(1, AngleSingle::Degrees(-45)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; @@ -58,7 +58,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 -45)"; - p = Polar(0, Angle::Degrees(0)); + p = Polar(0, AngleSingle::Degrees(0)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; @@ -67,7 +67,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(0 0)"; - p = Polar(-1, Angle::Degrees(0)); + p = Polar(-1, AngleSingle::Degrees(0)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; @@ -81,8 +81,8 @@ TEST(SphericalSingle, Incident1) { Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); SphericalSingle s = SphericalSingle ::FromVector3(v); - SphericalSingle sr = - SphericalSingle(2.49F, Angle::Degrees(98.18f), Angle::Degrees(24.4F)); + SphericalSingle sr = SphericalSingle(2.49F, AngleSingle::Degrees(98.18f), + AngleSingle::Degrees(24.4F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-02); @@ -99,8 +99,8 @@ TEST(SphericalSingle, Incident2) { Vector3 v = Vector3(1.0f, 0.0f, 1.0f); SphericalSingle s = SphericalSingle ::FromVector3(v); - SphericalSingle sr = SphericalSingle(1.4142135623F, Angle::Degrees(45.0f), - Angle::Degrees(0.0F)); + SphericalSingle sr = SphericalSingle( + 1.4142135623F, AngleSingle::Degrees(45.0f), AngleSingle::Degrees(0.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-05); @@ -115,8 +115,8 @@ TEST(SphericalSingle, Incident2) { v = Vector3(0.0f, 1.0f, 1.0f); s = SphericalSingle ::FromVector3(v); - sr = SphericalSingle(1.4142135623F, Angle::Degrees(0.0f), - Angle::Degrees(45.0F)); + sr = SphericalSingle(1.4142135623F, AngleSingle::Degrees(0.0f), + AngleSingle::Degrees(45.0F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-05); @@ -149,7 +149,7 @@ TEST(SphericalSingle, Incident2) { TEST(SphericalSingle, Addition) { SphericalSingle v1 = - SphericalSingle(1, Angle::Degrees(45), Angle::Degrees(0)); + SphericalSingle(1, AngleSingle::Degrees(45), AngleSingle::Degrees(0)); SphericalSingle v2 = SphericalSingle ::zero; SphericalSingle r = SphericalSingle ::zero; @@ -160,13 +160,13 @@ TEST(SphericalSingle, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; - v2 = SphericalSingle(1, Angle::Degrees(-45), Angle::Degrees(0)); + v2 = SphericalSingle(1, AngleSingle::Degrees(-45), AngleSingle::Degrees(0)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; - v2 = SphericalSingle(1, Angle::Degrees(0), Angle::Degrees(90)); + v2 = SphericalSingle(1, AngleSingle::Degrees(0), AngleSingle::Degrees(90)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index 3f8768e..05c95d8 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -1,7 +1,7 @@ #if GTEST #include -#include #include +#include #include "Vector2.h" @@ -462,16 +462,16 @@ TEST(Vector2, Rotate) { Vector2 v1 = Vector2(1, 2); Vector2 r = Vector2(0, 0); - r = Vector2::Rotate(v1, Angle::Degrees(0)); + r = Vector2::Rotate(v1, AngleSingle::Degrees(0)); EXPECT_FLOAT_EQ(Vector2::Distance(r, v1), 0); - r = Vector2::Rotate(v1, Angle::Degrees(180)); + r = Vector2::Rotate(v1, AngleSingle::Degrees(180)); EXPECT_NEAR(Vector2::Distance(r, Vector2(-1, -2)), 0, 1.0e-06); - r = Vector2::Rotate(v1, Angle::Degrees(-90)); + r = Vector2::Rotate(v1, AngleSingle::Degrees(-90)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); - r = Vector2::Rotate(v1, Angle::Degrees(270)); + r = Vector2::Rotate(v1, AngleSingle::Degrees(270)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); } From 89a57114a4840c68e0b333a4b6d3d8cc2073a97c Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 27 Dec 2024 23:20:11 +0100 Subject: [PATCH 119/121] Fixed typo in documentation --- Angle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Angle.h b/Angle.h index 27aac41..f8a215f 100644 --- a/Angle.h +++ b/Angle.h @@ -15,7 +15,7 @@ static float Deg2Rad = (pi * 2) / 360.0f; /// @brief An angle in various representations. /// @tparam T The internal type used for the representation of the angle. -/// The angle is internally limited to <-180..180] degrees or <-PI...PI] +/// The angle is internally limited to (-180..180] degrees or (-PI...PI] /// radians. When an angle exceeds this range, it is normalized to a value /// within the range. template class AngleOf { From 94a3105a61c2283d83e30c9e195f171fc3a6c014 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sat, 28 Dec 2024 10:04:04 +0100 Subject: [PATCH 120/121] Cleanup --- AngleAxis.h | 45 --------------------------------------------- Axis.cpp | 41 ----------------------------------------- Axis.h | 39 --------------------------------------- CMakeLists.txt | 4 ++-- Range.cpp | 48 ------------------------------------------------ Range.h | 50 -------------------------------------------------- 6 files changed, 2 insertions(+), 225 deletions(-) delete mode 100644 AngleAxis.h delete mode 100644 Axis.cpp delete mode 100644 Axis.h delete mode 100644 Range.cpp delete mode 100644 Range.h diff --git a/AngleAxis.h b/AngleAxis.h deleted file mode 100644 index 4d51c30..0000000 --- a/AngleAxis.h +++ /dev/null @@ -1,45 +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/. - -#ifndef ANGLEAXIS_H -#define ANGLEAXIS_H - -#include "Angle.h" -#include "Direction.h" -#include "Quaternion.h" - -namespace Passer { -namespace LinearAlgebra { - -// Isn't this the same as SphericalOf ????????????? - -template -class AngleAxisOf { - public: - float angle; - DirectionOf axis; - - AngleAxisOf(); - AngleAxisOf(float angle, DirectionOf axis); - AngleAxisOf(Quaternion q); - AngleAxisOf(float angle, Vector3 axis); - - const static AngleAxisOf zero; - - Quaternion ToQuaternion(); - - DirectionOf GetSwing(); -}; - -using AngleAxisSingle = AngleAxisOf; -using AngleAxis16 = AngleAxisOf; -using AngleAxis = AngleAxisOf; - -} // namespace LinearAlgebra -} // namespace Passer -using namespace Passer::LinearAlgebra; - -#endif -*/ \ No newline at end of file diff --git a/Axis.cpp b/Axis.cpp deleted file mode 100644 index 2403e4b..0000000 --- a/Axis.cpp +++ /dev/null @@ -1,41 +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 "Axis.h" - -#include "Quaternion.h" -#include "Vector3.h" - -#include - -Axis::Axis() { - horizontalAngle = Angle(); - verticalAngle = Angle(); -} - -Axis::Axis(Angle horizontal, Angle vertical) { - this->horizontalAngle = horizontal; - this->verticalAngle = vertical; -}; - -Axis::Axis(Vector3 v) { - this->horizontalAngle = - atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg; - this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg; -} - -const Axis Axis::forward = Axis(0.0f, 0.0f); -const Axis Axis::back = Axis(180.0f, 0.0f); -const Axis Axis::up = Axis(0.0f, 90.0f); -const Axis Axis::down = Axis(0.0f, -90.0f); -const Axis Axis::left = Axis(-90.0f, 0.0f); -const Axis Axis::right = Axis(90.0f, 0.0f); - -Vector3 Axis::ToVector3() { - Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()), - this->horizontalAngle.ToFloat(), 0) * - Vector3::forward; - return v; -} -*/ \ No newline at end of file diff --git a/Axis.h b/Axis.h deleted file mode 100644 index 971af2f..0000000 --- a/Axis.h +++ /dev/null @@ -1,39 +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/. -/* -#ifndef AXIS_H -#define AXIS_H - -#include "Angle.h" - -namespace Passer { -namespace LinearAlgebra { - -struct Vector3; - -class Axis { -public: - Angle horizontalAngle; - Angle verticalAngle; - - Axis(); - Axis(Angle horizontal, Angle vertical); - Axis(Vector3 v); - - const static Axis forward; - const static Axis back; - const static Axis up; - const static Axis down; - const static Axis left; - const static Axis right; - - Vector3 ToVector3(); -}; - -} // namespace LinearAlgebra -} // namespace Passer -using namespace Passer::LinearAlgebra; - -#endif -*/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c50090..38bbf0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,8 +32,8 @@ else() "Polar.cpp" "Spherical.cpp" "Matrix.cpp" - "Axis.cpp" - "AngleAxis.cpp" + # "Axis.cpp" + # "AngleAxis.cpp" "SwingTwist.cpp" "Direction.cpp" ) diff --git a/Range.cpp b/Range.cpp deleted file mode 100644 index d6b9e1b..0000000 --- a/Range.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "Range.h" - -/* -Range16::Range16() { this->range = 0; } - -Range16::Range16(float f) { - // clamp the float range to -1..1 - if (f < -1.0F) - f = -1.0F; - else if (f > 1.0F) - f = 1.0F; - - // map -1..1 to 0..65535 - this->range = (unsigned short)((f + 1.0F) * 65535.0F); -} - -Range16::Range16(short s) { - // clamp the range to -32767..32767 - // This is needed because the representation can support +/-32768 (like 2s - // complement) - if (s < -32767) - s = -32767; - else if (s > 32767) - s = 32767; - - this->range = (unsigned short)(s + 32767); -} - -Range16 Range16::operator-(Range16 a) { this->range - a.range; }; -Range16 Range16::operator+(Range16 a) { this->range + a.range; }; - -Range16 &Range16::operator-() { -this->range; } - -bool Range16::operator==(Range16 a) { this->range == a.range; } -bool Range16::operator!=(Range16 a) { return (this->range != a.range); } - -bool Range16::operator<(Range16 a) { return (this->range < a.range); } -bool Range16::operator>(Range16 a) { return (this->range > a.range); } -bool Range16::operator<=(Range16 a) { return (this->range <= a.range); } -bool Range16::operator>=(Range16 a) { return (this->range >= a.range); } -*/ - -template <> RangeUsing::RangeUsing(float f) { - this->value = (unsigned char)((f + 1.0f) * 127.0F); -} -template <> RangeUsing::RangeUsing(float f) { - this->value = (unsigned short)((f + 1.0F) * 32767.0F); -} \ No newline at end of file diff --git a/Range.h b/Range.h deleted file mode 100644 index 65f1dba..0000000 --- a/Range.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef RANGE_H -#define RANGE_H - -namespace Passer { -namespace LinearAlgebra { - -/* -/// @brief Signed range. May be renamed to SignedRange later -class Range16 { -public: - Range16(); - Range16(float range); // range -1..1 - Range16(short range); // range -32768..32767 - - inline Range16 operator-(Range16 a); - inline Range16 operator+(Range16 a); - inline virtual Range16 &operator-(); - - inline bool operator==(Range16 a); - inline bool operator!=(Range16 a); - - inline bool operator<(Range16 a); - inline bool operator>(Range16 a); - inline bool operator<=(Range16 a); - inline bool operator>=(Range16 a); - -protected: - // How do we make sure we have 16 bit range on every platform? - // uint16_t range; // 16-bit range - unsigned short range; // 16-bit range -}; -*/ - -template class RangeUsing { -public: - RangeUsing(float range); // range -1..1 - - inline RangeUsing operator-(RangeUsing a) { this->value - a.value; } - inline RangeUsing operator+(RangeUsing a) { this->value + a.value; } - inline RangeUsing operator-() { this->value = -this.value; } - inline T GetValue() { return value; } - - T value; -}; - -} // namespace LinearAlgebra -} // namespace Passer -using namespace Passer::LinearAlgebra; - -#endif \ No newline at end of file From 6f30334e12a3872deb3788cb00bac6edbcc9d6bb Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sat, 28 Dec 2024 10:19:13 +0100 Subject: [PATCH 121/121] Updated PolarOf, removed default Polar type --- Polar.cpp | 146 +++------------------------- Polar.h | 178 ++++++++--------------------------- Vector2.cpp | 2 +- test/Polar_test.cc | 84 +++++++++-------- test/SphericalSingle_test.cc | 10 +- test/Vector2_test.cc | 8 +- 6 files changed, 103 insertions(+), 325 deletions(-) diff --git a/Polar.cpp b/Polar.cpp index 92f4ba0..1f27ab9 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -21,6 +21,18 @@ template PolarOf::PolarOf(float distance, AngleOf angle) { } } +template +PolarOf PolarOf::Degrees(float distance, float degrees) { + AngleOf angle = AngleOf::Degrees(degrees); + PolarOf r = PolarOf(distance, angle); + return r; +} + +template +PolarOf PolarOf::Radians(float distance, float radians) { + return PolarOf(distance, AngleOf::Radians(radians)); +} + template PolarOf PolarOf::FromVector2(Vector2 v) { float distance = v.magnitude(); AngleOf angle = @@ -133,136 +145,4 @@ PolarOf PolarOf::Rotate(const PolarOf &v, AngleOf angle) { } template class PolarOf; -template class PolarOf; - -//===================================== -/* -Polar::Polar() { - this->distance = 0.0f; - this->angle = 0.0f; -} -Polar::Polar(float distance, Angle angle) { - // distance should always be 0 or greater - if (distance < 0.0f) { - this->distance = -distance; - this->angle = Angle::Normalize(angle.ToFloat() - 180.0f); - } else { - this->distance = distance; - if (this->distance == 0.0f) - // angle is always 0 if distance is 0 - this->angle = 0.0f; - else - this->angle = Angle::Normalize(angle); - } -} -Polar::Polar(Vector2 v) { - this->distance = v.magnitude(); - this->angle = Vector2::SignedAngle(Vector2::forward, v); -} -Polar::Polar(Spherical v) { - this->distance = v.distance * cosf(v.verticalAngle.ToFloat() * - Passer::LinearAlgebra::Deg2Rad); - this->angle = v.horizontalAngle; -} - -const Polar Polar::zero = Polar(0.0f, 0.0f); -const Polar Polar::forward = Polar(1.0f, 0.0f); -const Polar Polar::back = Polar(1.0, 180.0f); -const Polar Polar::right = Polar(1.0, 90.0f); -const Polar Polar::left = Polar(1.0, -90.0f); - -bool Polar::operator==(const Polar& v) const { - return (this->distance == v.distance && - this->angle.ToFloat() == v.angle.ToFloat()); -} - -Polar Polar::Normalize(const Polar& v) { - Polar r = Polar(1, v.angle); - return r; -} -Polar Polar::normalized() const { - Polar r = Polar(1, this->angle); - return r; -} - -Polar Polar::operator-() const { - Polar v = Polar(this->distance, this->angle.ToFloat() + 180.0f); - return v; -} - -Polar Polar::operator-(const Polar& v) const { - Polar r = -v; - return *this + r; -} -Polar Polar::operator-=(const Polar& v) { - *this = *this - v; - return *this; -} -Polar Polar::operator+(const Polar& v) const { - if (v.distance == 0) - return Polar(this->distance, this->angle); - if (this->distance == 0.0f) - return v; - - float deltaAngle = - Angle::Normalize(v.angle.ToFloat() - this->angle.ToFloat()).ToFloat(); - float rotation = - deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle; - - if (rotation == 180.0f && v.distance > 0.0f) { - // angle is too small, take this angle and add the distances - return Polar(this->distance + v.distance, this->angle); - } - - float newDistance = - Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat(); - - float angle = - Angle::CosineRuleAngle(newDistance, this->distance, -v.distance).ToFloat(); - - float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle - : this->angle.ToFloat() + angle; - newAngle = Angle::Normalize(newAngle).ToFloat(); - Polar vector = Polar(newDistance, newAngle); - return vector; -} -Polar Polar::operator+=(const Polar& v) { - *this = *this + v; - return *this; -} - -// Polar Passer::LinearAlgebra::operator*(const Polar &v, float f) { -// return Polar(v.distance * f, v.angle); -// } -// Polar Passer::LinearAlgebra::operator*(float f, const Polar &v) { -// return Polar(v.distance * f, v.angle); -// } -Polar Polar::operator*=(float f) { - this->distance *= f; - return *this; -} -// Polar Passer::LinearAlgebra::operator/(const Polar& v, float f) { -// return Polar(v.distance / f, v.angle); -// } -// Polar Passer::LinearAlgebra::operator/(float f, const Polar& v) { -// return Polar(v.distance / f, v.angle); -// } -Polar Polar::operator/=(float f) { - this->distance /= f; - return *this; -} - -float Polar::Distance(const Polar& v1, const Polar& v2) { - float d = Angle::CosineRuleSide(v1.distance, v2.distance, - v2.angle.ToFloat() - v1.angle.ToFloat()) - .ToFloat(); - return d; -} - -Polar Polar::Rotate(const Polar& v, Angle angle) { - Angle a = Angle::Normalize(v.angle.ToFloat() + angle.ToFloat()); - Polar r = Polar(v.distance, a); - return r; -} -*/ +template class PolarOf; \ No newline at end of file diff --git a/Polar.h b/Polar.h index 3264880..e1c746f 100644 --- a/Polar.h +++ b/Polar.h @@ -11,12 +11,10 @@ namespace Passer { namespace LinearAlgebra { struct Vector2; -template -class SphericalOf; +template class SphericalOf; -template -class PolarOf { - public: +template class PolarOf { +public: /// @brief The distance in meters /// @remark The distance shall never be negative float distance; @@ -33,6 +31,24 @@ class PolarOf { /// @note The distance is automatically converted to a positive value. /// @note The angle is automatically normalized to -180 .. 180 PolarOf(float distance, AngleOf angle); + + /// @brief Create polar vector without using AngleOf type. All given angles + /// are in degrees + /// @param distance The distance in meters + /// @param degrees The angle in degrees + /// @return The polar vector + static PolarOf Degrees(float distance, float degrees); + /// @brief Short-hand Deg alias for the Degrees function + constexpr static auto Deg = Degrees; + /// @brief Create polar vector without using AngleOf type. All given angles + /// are in radians. + /// @param distance The distance in meters + /// @param radians The angle in radians + /// @return The polar vector + static PolarOf Radians(float distance, float radians); + /// @brief Short-hand Rad alias for the Radians function + constexpr static auto Rad = Radians; + /// @brief Convert a vector from 2D carthesian coordinates to polar /// coordinates /// @param v The vector to convert @@ -58,12 +74,12 @@ class PolarOf { /// @return true: if it is identical to the given vector /// @note This uses float comparison to check equality which may have /// strange effects. Equality on floats should be avoided. - bool operator==(const PolarOf& v) const; + bool operator==(const PolarOf &v) const; /// @brief The vector length /// @param v The vector for which you need the length /// @return The vector length; - inline static float Magnitude(const PolarOf& v) { return v.distance; } + inline static float Magnitude(const PolarOf &v) { return v.distance; } /// @brief The vector length /// @return The vector length inline float magnitude() const { return this->distance; } @@ -71,7 +87,7 @@ class PolarOf { /// @brief Convert the vector to a length of 1 /// @param v The vector to convert /// @return The vector normalized to a length of 1 - static PolarOf Normalize(const PolarOf& v); + static PolarOf Normalize(const PolarOf &v); /// @brief Convert the vector to a length of a /// @return The vector normalized to a length of 1 PolarOf normalized() const; @@ -84,23 +100,23 @@ class PolarOf { /// @brief Subtract a polar vector from this vector /// @param v The vector to subtract /// @return The result of the subtraction - PolarOf operator-(const PolarOf& v) const; - PolarOf operator-=(const PolarOf& v); + PolarOf operator-(const PolarOf &v) const; + PolarOf operator-=(const PolarOf &v); /// @brief Add a polar vector to this vector /// @param v The vector to add /// @return The result of the addition - PolarOf operator+(const PolarOf& v) const; - PolarOf operator+=(const PolarOf& v); + PolarOf operator+(const PolarOf &v) const; + PolarOf operator+=(const PolarOf &v); /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend PolarOf operator*(const PolarOf& v, float f) { + friend PolarOf operator*(const PolarOf &v, float f) { return PolarOf(v.distance * f, v.angle); } - friend PolarOf operator*(float f, const PolarOf& v) { + friend PolarOf operator*(float f, const PolarOf &v) { return PolarOf(f * v.distance, v.angle); } PolarOf operator*=(float f); @@ -109,10 +125,10 @@ class PolarOf { /// @return The scaled factor /// @remark This operation will scale the distance of the vector. The angle /// will be unaffected. - friend PolarOf operator/(const PolarOf& v, float f) { + friend PolarOf operator/(const PolarOf &v, float f) { return PolarOf(v.distance / f, v.angle); } - friend PolarOf operator/(float f, const PolarOf& v) { + friend PolarOf operator/(float f, const PolarOf &v) { return PolarOf(f / v.distance, v.angle); } PolarOf operator/=(float f); @@ -121,141 +137,21 @@ class PolarOf { /// @param v1 The first vector /// @param v2 The second vector /// @return The distance between the two vectors - static float Distance(const PolarOf& v1, const PolarOf& v2); + static float Distance(const PolarOf &v1, const PolarOf &v2); /// @brief Rotate a vector /// @param v The vector to rotate /// @param a The angle in degreesto rotate /// @return The rotated vector - static PolarOf Rotate(const PolarOf& v, AngleOf a); + static PolarOf Rotate(const PolarOf &v, AngleOf a); }; using PolarSingle = PolarOf; using Polar16 = PolarOf; -using Polar = PolarSingle; +// using Polar = PolarSingle; -/* -/// @brief A polar vector -/// @details This will use the polar coordinate system consisting of a angle -/// from a reference direction and a distance. -struct Polar { - public: - /// @brief The distance in meters - /// @remark The distance shall never be negative - float distance; - /// @brief The angle in degrees clockwise rotation - /// @remark The angle shall be between -180 .. 180 - Angle angle; - - /// @brief A new vector with polar coordinates with zero degrees and - /// distance - Polar(); - /// @brief A new vector with polar coordinates - /// @param distance The distance in meters - /// @param angle The angle in degrees, clockwise rotation - /// @note The distance is automatically converted to a positive value. - /// @note The angle is automatically normalized to -180 .. 180 - Polar(float distance, Angle angle); - /// @brief Convert a vector from 2D carthesian coordinates to polar - /// coordinates - /// @param v The vector to convert - Polar(Vector2 v); - /// @brief Convert a vector from spherical coordinates to polar coordinates - /// @param s The vector to convert - /// @note The resulting vector will be projected on the horizontal plane - Polar(Spherical s); - - /// @brief A polar vector with zero degrees and distance - const static Polar zero; - /// @brief A normalized forward-oriented vector - const static Polar forward; - /// @brief A normalized back-oriented vector - const static Polar back; - /// @brief A normalized right-oriented vector - const static Polar right; - /// @brief A normalized left-oriented vector - const static Polar left; - - /// @brief Equality test to another vector - /// @param v The vector to check against - /// @return true: if it is identical to the given vector - /// @note This uses float comparison to check equality which may have - /// strange effects. Equality on floats should be avoided. - bool operator==(const Polar& v) const; - - /// @brief The vector length - /// @param v The vector for which you need the length - /// @return The vector length; - inline static float Magnitude(const Polar& v) { return v.distance; } - /// @brief The vector length - /// @return The vector length - inline float magnitude() const { return this->distance; } - - /// @brief Convert the vector to a length of 1 - /// @param v The vector to convert - /// @return The vector normalized to a length of 1 - static Polar Normalize(const Polar& v); - /// @brief Convert the vector to a length of a - /// @return The vector normalized to a length of 1 - Polar normalized() const; - - /// @brief Negate the vector - /// @return The negated vector - /// This will rotate the vector by 180 degrees. Distance will stay the same. - Polar operator-() const; - - /// @brief Subtract a polar vector from this vector - /// @param v The vector to subtract - /// @return The result of the subtraction - Polar operator-(const Polar& v) const; - Polar operator-=(const Polar& v); - /// @brief Add a polar vector to this vector - /// @param v The vector to add - /// @return The result of the addition - Polar operator+(const Polar& v) const; - Polar operator+=(const Polar& v); - - /// @brief Scale the vector uniformly up - /// @param f The scaling factor - /// @return The scaled vector - /// @remark This operation will scale the distance of the vector. The angle - /// will be unaffected. - friend Polar operator*(const Polar& v, float f) { - return Polar(v.distance * f, v.angle); - } - friend Polar operator*(float f, const Polar& v) { - return Polar(f * v.distance, v.angle); - } - Polar operator*=(float f); - /// @brief Scale the vector uniformly down - /// @param f The scaling factor - /// @return The scaled factor - /// @remark This operation will scale the distance of the vector. The angle - /// will be unaffected. - friend Polar operator/(const Polar& v, float f) { - return Polar(v.distance / f, v.angle); - } - friend Polar operator/(float f, const Polar& v) { - return Polar(f / v.distance, v.angle); - } - Polar operator/=(float f); - - /// @brief The distance between two vectors - /// @param v1 The first vector - /// @param v2 The second vector - /// @return The distance between the two vectors - static float Distance(const Polar& v1, const Polar& v2); - - /// @brief Rotate a vector - /// @param v The vector to rotate - /// @param a The angle in degreesto rotate - /// @return The rotated vector - static Polar Rotate(const Polar& v, Angle a); -}; -*/ - -} // namespace LinearAlgebra -} // namespace Passer +} // namespace LinearAlgebra +} // namespace Passer using namespace Passer::LinearAlgebra; #include "Spherical.h" diff --git a/Vector2.cpp b/Vector2.cpp index e895992..69e9deb 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -29,7 +29,7 @@ Vector2::Vector2(Vector3 v) { x = v.Right(); // x; y = v.Forward(); // z; } -Vector2::Vector2(Polar p) { +Vector2::Vector2(PolarSingle p) { float horizontalRad = p.angle.InDegrees() * Passer::LinearAlgebra::Deg2Rad; float cosHorizontal = cosf(horizontalRad); float sinHorizontal = sinf(horizontalRad); diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 7f93074..9e244f2 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -10,19 +10,19 @@ TEST(Polar, FromVector2) { Vector2 v = Vector2(0, 1); - Polar p = Polar::FromVector2(v); + PolarSingle p = PolarSingle::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "s.angle 0 0 1"; v = Vector2(1, 0); - p = Polar::FromVector2(v); + p = PolarSingle::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 90.0F) << "s.angle 1 0"; v = Vector2(-1, 1); - p = Polar::FromVector2(v); + p = PolarSingle::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1"; EXPECT_NEAR(p.angle.InDegrees(), -45.0F, 1.0e-05) << "s.angle -1 1"; @@ -30,94 +30,96 @@ TEST(Polar, FromVector2) { TEST(Polar, FromSpherical) { SphericalSingle s; - Polar p; + PolarSingle p; - s = SphericalSingle(1, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); - p = Polar::FromSpherical(s); + s = SphericalSingle(1, DirectionSingle::forward); + p = PolarSingle::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(1 0 0)"; s = SphericalSingle(1, AngleSingle::Degrees(45), AngleSingle::Degrees(0)); - p = Polar::FromSpherical(s); + p = PolarSingle::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 45.0F) << "p.angle FromSpherical(1 45 0)"; s = SphericalSingle(1, AngleSingle::Degrees(-45), AngleSingle::Degrees(0)); - p = Polar::FromSpherical(s); + p = PolarSingle::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -45.0F) << "p.angle FromSpherical(1 -45 0)"; s = SphericalSingle(0, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); - p = Polar::FromSpherical(s); + p = PolarSingle::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 0)"; s = SphericalSingle(-1, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); - p = Polar::FromSpherical(s); + p = PolarSingle::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -180.0F) << "p.angle FromSpherical(-1 0 0)"; s = SphericalSingle(0, AngleSingle::Degrees(0), AngleSingle::Degrees(90)); - p = Polar::FromSpherical(s); + p = PolarSingle::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 90)"; } TEST(Polar, Negation) { - Polar v = Polar(2, AngleSingle::Degrees(45)); - Polar r = Polar::zero; + PolarSingle v = PolarSingle(2, AngleSingle::Degrees(45)); + PolarSingle r = PolarSingle::zero; r = -v; EXPECT_FLOAT_EQ(r.distance, 2); EXPECT_FLOAT_EQ(r.angle.InDegrees(), -135); - EXPECT_TRUE(r == Polar(2, AngleSingle::Degrees(-135))) << "Negate(2 45)"; + EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(-135))) + << "Negate(2 45)"; - v = Polar(2, AngleSingle::Degrees(-45)); + v = PolarSingle::Deg(2, -45); r = -v; - EXPECT_TRUE(r == Polar(2, AngleSingle::Degrees(135))) << "Negate(2 -45)"; + EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(135))) + << "Negate(2 -45)"; - v = Polar(2, AngleSingle::Degrees(0)); + v = PolarSingle::Degrees(2, 0); r = -v; - EXPECT_TRUE(r == Polar(2, AngleSingle::Degrees(180))) << "Negate(2 0)"; + EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(180))) << "Negate(2 0)"; - v = Polar(0, AngleSingle::Degrees(0)); + v = PolarSingle(0, AngleSingle::Degrees(0)); r = -v; EXPECT_FLOAT_EQ(r.distance, 0.0f); EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0.0f); - EXPECT_TRUE(r == Polar(0, AngleSingle::Degrees(0))) << "Negate(0 0)"; + EXPECT_TRUE(r == PolarSingle(0, AngleSingle::Degrees(0))) << "Negate(0 0)"; } TEST(Polar, Subtraction) { - Polar v1 = Polar(4, AngleSingle::Degrees(45)); - Polar v2 = Polar(1, AngleSingle::Degrees(-90)); - Polar r = Polar::zero; + PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); + PolarSingle v2 = PolarSingle(1, AngleSingle::Degrees(-90)); + PolarSingle r = PolarSingle::zero; r = v1 - v2; // don't know what to expect yet - v2 = Polar::zero; + v2 = PolarSingle::zero; r = v1 - v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Subtraction(0 0)"; } TEST(Polar, Addition) { - Polar v1 = Polar(1, AngleSingle::Degrees(45)); - Polar v2 = Polar(1, AngleSingle::Degrees(-90)); - Polar r = Polar::zero; + PolarSingle v1 = PolarSingle(1, AngleSingle::Degrees(45)); + PolarSingle v2 = PolarSingle(1, AngleSingle::Degrees(-90)); + PolarSingle r = PolarSingle::zero; r = v1 - v2; // don't know what to expect yet - v2 = Polar::zero; + v2 = PolarSingle::zero; r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; @@ -125,15 +127,15 @@ TEST(Polar, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; - v2 = Polar(1, AngleSingle::Degrees(-45)); + v2 = PolarSingle(1, AngleSingle::Degrees(-45)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0) << "Addition(0 0 0)"; } TEST(Polar, Scale_Multiply) { - Polar v1 = Polar(4, AngleSingle::Degrees(45)); - Polar r = Polar::zero; + PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); + PolarSingle r = PolarSingle::zero; r = v1 * 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance * 2) << "ScaleMult(4 45, 2)"; @@ -142,8 +144,8 @@ TEST(Polar, Scale_Multiply) { } TEST(Polar, Scale_Divide) { - Polar v1 = Polar(4, AngleSingle::Degrees(45)); - Polar r = Polar::zero; + PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); + PolarSingle r = PolarSingle::zero; r = v1 / 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance / 2) << "ScaleDiv(4 45, 2)"; @@ -152,23 +154,23 @@ TEST(Polar, Scale_Divide) { } TEST(Polar, Distance) { - Polar v1 = Polar(4, AngleSingle::Degrees(45)); - Polar v2 = Polar(1, AngleSingle::Degrees(-90)); + PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); + PolarSingle v2 = PolarSingle(1, AngleSingle::Degrees(-90)); float d = 0; - d = Polar::Distance(v1, v2); + d = PolarSingle::Distance(v1, v2); // don't know what to expect yet - v2 = Polar::zero; - d = Polar::Distance(v1, v2); + v2 = PolarSingle::zero; + d = PolarSingle::Distance(v1, v2); EXPECT_FLOAT_EQ(d, v1.distance) << "Distance(4 45, zero)"; } TEST(Polar, Rotate) { - Polar v = Polar(4, AngleSingle::Degrees(45)); - Polar r = Polar::zero; + PolarSingle v = PolarSingle(4, AngleSingle::Degrees(45)); + PolarSingle r = PolarSingle::zero; - r = Polar::Rotate(v, AngleSingle::Degrees(45)); + r = PolarSingle::Rotate(v, AngleSingle::Degrees(45)); EXPECT_FLOAT_EQ(r.distance, v.distance) << "Rotate(4 45, 45)"; EXPECT_FLOAT_EQ(r.angle.InDegrees(), 90.0f) << "Rotate(4 45, 45)"; } diff --git a/test/SphericalSingle_test.cc b/test/SphericalSingle_test.cc index e77276a..7840d77 100644 --- a/test/SphericalSingle_test.cc +++ b/test/SphericalSingle_test.cc @@ -31,7 +31,7 @@ TEST(SphericalSingle, FromVector3) { } TEST(SphericalSingle, FromPolar) { - Polar p = Polar(1, AngleSingle::Degrees(0)); + PolarSingle p = PolarSingle(1, AngleSingle::Degrees(0)); SphericalSingle s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; @@ -40,7 +40,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 0)"; - p = Polar(1, AngleSingle::Degrees(45)); + p = PolarSingle(1, AngleSingle::Degrees(45)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; @@ -49,7 +49,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 45)"; - p = Polar(1, AngleSingle::Degrees(-45)); + p = PolarSingle(1, AngleSingle::Degrees(-45)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; @@ -58,7 +58,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 -45)"; - p = Polar(0, AngleSingle::Degrees(0)); + p = PolarSingle(0, AngleSingle::Degrees(0)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; @@ -67,7 +67,7 @@ TEST(SphericalSingle, FromPolar) { EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert Polar(0 0)"; - p = Polar(-1, AngleSingle::Degrees(0)); + p = PolarSingle(-1, AngleSingle::Degrees(0)); s = SphericalSingle ::FromPolar(p); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index 05c95d8..3afeb4b 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -9,25 +9,25 @@ TEST(Vector2, FromPolar) { Vector2 v; - Polar p; + PolarSingle p; Vector2 r; v = Vector2(0, 1); - p = Polar::FromVector2(v); + p = PolarSingle::FromVector2(v); r = Vector2(p); EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 1)"; EXPECT_FLOAT_EQ(r.y, 1.0F) << "FromPolar(0 1)"; v = Vector2(1, 0); - p = Polar::FromVector2(v); + p = PolarSingle::FromVector2(v); r = Vector2(p); EXPECT_FLOAT_EQ(r.x, 1.0F) << "FromPolar(1 0)"; EXPECT_NEAR(r.y, 0.0F, 1.0e-07) << "FromPolar(1 0)"; v = Vector2(0, 0); - p = Polar::FromVector2(v); + p = PolarSingle::FromVector2(v); r = Vector2(p); EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 0)";