diff --git a/LinearAlgebra/.gitlab-ci.yml b/LinearAlgebra/.gitlab-ci.yml index 6b28d70..40f9eec 100644 --- a/LinearAlgebra/.gitlab-ci.yml +++ b/LinearAlgebra/.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: diff --git a/LinearAlgebra/Angle.cpp b/LinearAlgebra/Angle.cpp index 4a039ce..c88afdc 100644 --- a/LinearAlgebra/Angle.cpp +++ b/LinearAlgebra/Angle.cpp @@ -6,10 +6,9 @@ #include "FloatSingle.h" #include +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; @@ -20,106 +19,301 @@ 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 <> Angle2 Angle2::pi = 3.1415927410125732421875F; +template AngleOf::AngleOf() : value(0) {} -template <> Angle2 Angle2::Rad2Deg = 360.0f / (pi * 2); -template <> Angle2 Angle2::Deg2Rad = (pi * 2) / 360.0f; +template const AngleOf AngleOf::zero = AngleOf(); +// template +// const AngleOf AngleOf::deg90 = AngleOf::Degrees(90); +// template +// const AngleOf AngleOf::deg180 = AngleOf::Degrees(180); -template <> Angle2 Angle2::Normalize(Angle2 angle) { - float angleValue = angle; +//===== AngleSingle, AngleOf + +template <> AngleOf AngleOf::Degrees(float degrees) { + if (isfinite(degrees)) { + while (degrees < -180) + degrees += 360; + while (degrees >= 180) + degrees -= 360; + } + + return Binary(degrees); +} + +template <> AngleOf AngleOf::Radians(float radians) { + if (isfinite(radians)) { + while (radians <= -pi) + radians += 2 * pi; + while (radians > pi) + radians -= 2 * pi; + } + + return Binary(radians * Rad2Deg); +} + +template <> float AngleOf::InDegrees() const { return this->value; } + +template <> float AngleOf::InRadians() const { + return this->value * Deg2Rad; +} + +//===== Angle16, AngleOf + +template <> +AngleOf AngleOf::Degrees(float degrees) { + // map float [-180..180) to integer [-32768..32767] + signed short value = (signed short)roundf(degrees / 360.0F * 65536.0F); + return Binary(value); +} + +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(radians / pi * 32768.0F); + return Binary(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 degrees) { + // map float [-180..180) to integer [-128..127) + signed char value = (signed char)roundf(degrees / 360.0F * 256.0F); + return Binary(value); +} + +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(radians / pi * 128.0f); + return Binary(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 AngleOf AngleOf::Binary(T rawValue) { + AngleOf angle = AngleOf(); + angle.SetBinary(rawValue); + return angle; +} + +template T AngleOf::GetBinary() const { return this->value; } +template void AngleOf::SetBinary(T rawValue) { + this->value = rawValue; +} + +template +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 (angle.value > 0) + return 1; + return 0; +} + +template +AngleOf Passer::LinearAlgebra::AngleOf::Abs(AngleOf angle) { + if (Sign(angle) < 0) + return -angle; + else + return angle; +} + +template AngleOf AngleOf::operator-() const { + AngleOf angle = Binary(-this->value); + return angle; +} + +template <> +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 &angle) const { + AngleOf r = Binary(this->value - angle.value); + return r; +} + +template <> +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 &angle) const { + AngleOf r = Binary(this->value + angle.value); + return r; +} + +template <> +AngleOf AngleOf::operator+=(const AngleOf &angle) { + this->value += angle.value; + this->Normalize(); + return *this; +} + +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)) - return angleValue; + return; while (angleValue <= -180) angleValue += 360; while (angleValue > 180) angleValue -= 360; - return angleValue; + *this = AngleOf::Degrees(angleValue); } -template <> -Angle2 Angle2::Clamp(Angle2 angle, Angle2 min, - Angle2 max) { - float normalizedAngle = Normalize(angle); - float r = Float::Clamp(normalizedAngle, min, max); - return r; +template AngleOf AngleOf::Normalize(AngleOf angle) { + float angleValue = angle.InDegrees(); + if (!isfinite(angleValue)) + return angle; + + while (angleValue <= -180) + angleValue += 360; + while (angleValue > 180) + angleValue -= 360; + return AngleOf::Degrees(angleValue); } -// template -// Angle2 Angle2::Difference(Angle2 a, Angle2 b) { -// Angle2 r = Normalize(b - a); -// 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, + 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; -template <> -Angle2 Angle2::MoveTowards(Angle2 fromAngle, - Angle2 toAngle, - Angle2 maxAngle) { - float d = toAngle - fromAngle; - float sign = signbit(d) ? -1 : 1; - d = sign * Float::Clamp(fabs(d), 0, maxAngle); return fromAngle + d; } -template <> -Angle2 Angle2::CosineRuleSide(float a, float b, - Angle2 gamma) { +template float AngleOf::Cos(AngleOf angle) { + return cosf(angle.InRadians()); +} +template float AngleOf::Sin(AngleOf angle) { + return sinf(angle.InRadians()); +} +template float AngleOf::Tan(AngleOf angle) { + return tanf(angle.InRadians()); +} + +template 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 Passer::LinearAlgebra::AngleOf::Atan2(float y, float x) { + return AngleOf::Radians(atan2f(y, x)); +} + +// 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 * cos(gamma * Angle2::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; @@ -128,25 +322,54 @@ Angle2 Angle2::CosineRuleSide(float a, float b, return c; } -template <> -Angle2 Angle2::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; + return AngleOf(); if (d <= -1) - return 180; + return AngleOf::Degrees(180); - float gamma = acos(d) * Angle::Rad2Deg; + // float gamma = acosf(d) * Rad2Deg; + AngleOf gamma = Acos(d); return gamma; } -template <> -Angle2 Angle2::SineRuleAngle(float a, Angle2 beta, - float b) { - float alpha = asin(a * sin(beta * Angle::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; -} \ No newline at end of file +} + +template class AngleOf; +template class AngleOf; +template class AngleOf; \ No newline at end of file diff --git a/LinearAlgebra/Angle.h b/LinearAlgebra/Angle.h index edabf65..f8a215f 100644 --- a/LinearAlgebra/Angle.h +++ b/LinearAlgebra/Angle.h @@ -5,51 +5,222 @@ #ifndef ANGLE_H #define ANGLE_H -template class Angle2 { +namespace Passer { +namespace LinearAlgebra { + +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: - Angle2(){}; - Angle2(T v) : value(v) {} - operator T() { return value; } + /// @brief Create a new angle with a zero value + AngleOf(); - static Angle2 Rad2Deg; - static Angle2 Deg2Rad; + /// @brief An zero value angle + const static AngleOf zero; + // const static AngleOf deg90; + // const static AngleOf deg180; - static Angle2 pi; + /// @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); - 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); - return r; - }; - static Angle2 MoveTowards(Angle2 fromAngle, Angle2 toAngle, - Angle2 maxAngle); + /// @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; - static Angle2 CosineRuleSide(float a, float b, Angle2 gamma); - static Angle2 CosineRuleAngle(float a, float b, float c); + /// @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); - static Angle2 SineRuleAngle(float a, Angle2 beta, float c); + /// @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; + + /// @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; + /// @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); + + /// @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); + } + /// @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); + /// @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); + + /// @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); + /// @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); }; -using Angle = Angle2; -/* -class Angle { -public: - const static float Rad2Deg; - const static float Deg2Rad; +// using Angle = AngleOf; +using AngleSingle = AngleOf; +using Angle16 = AngleOf; +using Angle8 = AngleOf; - 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); +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; - 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); -}; -*/ #endif \ No newline at end of file diff --git a/LinearAlgebra/AngleAxis.cpp b/LinearAlgebra/AngleAxis.cpp new file mode 100644 index 0000000..6e17e51 --- /dev/null +++ b/LinearAlgebra/AngleAxis.cpp @@ -0,0 +1,53 @@ +/* +// 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" + +template +AngleAxisOf::AngleAxisOf() { + this->angle = 0.0F; + this->axis = DirectionOf(); +} + +template +AngleAxisOf::AngleAxisOf(float angle, DirectionOf axis) { + this->angle = angle; + this->axis = axis; +} + +template +AngleAxisOf::AngleAxisOf(float angle, Vector3 axis) { + this->angle = angle; + this->axis = DirectionOf::FromVector3(axis); +} + +template +AngleAxisOf::AngleAxisOf(Quaternion q) { + float angle; + Vector3 axis; + q.ToAngleAxis(&angle, &axis); + this->angle = angle; + this->axis = DirectionOf::FromVector3(axis); +} + +template +const AngleAxisOf AngleAxisOf::zero = + AngleAxisOf(0.0, DirectionOf(AngleOf(), AngleOf())); + +template +Quaternion AngleAxisOf::ToQuaternion() { + Vector3 axisVector = this->axis.ToVector3(); + Quaternion q = Quaternion::AngleAxis(this->angle, axisVector); + return q; +} + +template +DirectionOf AngleAxisOf::GetSwing() { + return this->axis; +} + +template class AngleAxisOf; +template class AngleAxisOf; +*/ \ No newline at end of file diff --git a/LinearAlgebra/AngleUsing.h b/LinearAlgebra/AngleUsing.h new file mode 100644 index 0000000..f2bc80e --- /dev/null +++ b/LinearAlgebra/AngleUsing.h @@ -0,0 +1,52 @@ +/* +#ifndef DISCRETEANGLE_H +#define DISCRETEANGLE_H + +#include "Angle.h" +#include "Range.h" + +namespace Passer { +namespace LinearAlgebra { + +// 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((float)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; +}; + +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#endif +*/ \ No newline at end of file diff --git a/LinearAlgebra/CMakeLists.txt b/LinearAlgebra/CMakeLists.txt index d61999d..38bbf0c 100644 --- a/LinearAlgebra/CMakeLists.txt +++ b/LinearAlgebra/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) @@ -14,6 +14,7 @@ else() include(FetchContent) FetchContent_Declare( googletest + DOWNLOAD_EXTRACT_TIMESTAMP URL https://github.com/google/googletest/archive/refs/heads/main.zip ) @@ -22,7 +23,7 @@ else() FetchContent_MakeAvailable(googletest) include_directories(.) - add_library(VectorAlgebra STATIC + add_library(LinearAlgebra STATIC "FloatSingle.cpp" "Angle.cpp" "Vector2.cpp" @@ -31,26 +32,33 @@ else() "Polar.cpp" "Spherical.cpp" "Matrix.cpp" + # "Axis.cpp" + # "AngleAxis.cpp" + "SwingTwist.cpp" + "Direction.cpp" ) enable_testing() + file(GLOB_RECURSE test_srcs test/*_test.cc) add_executable( - VectorAlgebraTest - "test/Angle_test.cc" - "test/FloatSingle_test.cc" - "test/Vector2_test.cc" - "test/Vector3_test.cc" - "test/Quaternion_test.cc" - "test/Matrix_test.cc" + LinearAlgebraTest + ${test_srcs} ) target_link_libraries( - VectorAlgebraTest + LinearAlgebraTest gtest_main - VectorAlgebra + LinearAlgebra ) + if(MSVC) + target_compile_options(LinearAlgebraTest PRIVATE /W4 /WX) + else() + target_compile_options(LinearAlgebraTest PRIVATE -Wall -Wextra -Wpedantic -Werror) + endif() + + include(GoogleTest) - gtest_discover_tests(VectorAlgebraTest) + gtest_discover_tests(LinearAlgebraTest) endif() diff --git a/LinearAlgebra/Direction.cpp b/LinearAlgebra/Direction.cpp new file mode 100644 index 0000000..c465b4a --- /dev/null +++ b/LinearAlgebra/Direction.cpp @@ -0,0 +1,111 @@ +// 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 +DirectionOf::DirectionOf() { + this->horizontal = AngleOf(); + this->vertical = AngleOf(); +} + +template +DirectionOf::DirectionOf(AngleOf horizontal, AngleOf vertical) { + this->horizontal = horizontal; + this->vertical = vertical; + Normalize(); +}; + +template +const DirectionOf DirectionOf::forward = + DirectionOf(AngleOf(), AngleOf()); +template +const DirectionOf DirectionOf::back = + DirectionOf(AngleOf::Degrees(180), AngleOf()); +template +const DirectionOf DirectionOf::up = + DirectionOf(AngleOf(), AngleOf::Degrees(90)); +template +const DirectionOf DirectionOf::down = + DirectionOf(AngleOf(), AngleOf::Degrees(-90)); +template +const DirectionOf DirectionOf::left = + DirectionOf(AngleOf::Degrees(-90), AngleOf()); +template +const DirectionOf DirectionOf::right = + DirectionOf(AngleOf::Degrees(90), 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::Degrees(-90) - + 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) { + 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 + AngleOf::Degrees(180), + -this->vertical); + return r; +} + +template +Vector3 DirectionOf::ToVector3() { + Vector3 v = Quaternion::Euler(-this->vertical.InDegrees(), + this->horizontal.InDegrees(), 0) * + Vector3::forward; + 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/LinearAlgebra/Direction.h b/LinearAlgebra/Direction.h new file mode 100644 index 0000000..79ca814 --- /dev/null +++ b/LinearAlgebra/Direction.h @@ -0,0 +1,57 @@ +// 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 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); + + Vector3 ToVector3() const; + static DirectionOf FromVector3(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; + const static DirectionOf down; + const static DirectionOf left; + const static DirectionOf right; + + bool operator==(const DirectionOf d) const; + + DirectionOf operator-() const; + + Vector3 ToVector3(); + + protected: + void Normalize(); +}; + +using DirectionSingle = DirectionOf; +using Direction16 = DirectionOf; +using Direction = DirectionOf; + +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#endif \ No newline at end of file diff --git a/LinearAlgebra/DoxyGen/DoxyWarnLogfile.txt b/LinearAlgebra/DoxyGen/DoxyWarnLogfile.txt index d37d508..b1425a0 100644 --- a/LinearAlgebra/DoxyGen/DoxyWarnLogfile.txt +++ b/LinearAlgebra/DoxyGen/DoxyWarnLogfile.txt @@ -1,420 +1,122 @@ -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 > &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 + '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 > &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 + '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 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 + '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. +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/LinearAlgebra/DoxyGen/Doxyfile b/LinearAlgebra/DoxyGen/Doxyfile index 8f5e552..335a8f2 100644 --- a/LinearAlgebra/DoxyGen/Doxyfile +++ b/LinearAlgebra/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/LinearAlgebra/FloatSingle.cpp b/LinearAlgebra/FloatSingle.cpp index fb6f301..902d85e 100644 --- a/LinearAlgebra/FloatSingle.cpp +++ b/LinearAlgebra/FloatSingle.cpp @@ -2,16 +2,18 @@ // 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; + if (max < min) return f; + if (f < min) + return min; + if (f > max) + return max; + return f; } \ No newline at end of file diff --git a/LinearAlgebra/FloatSingle.h b/LinearAlgebra/FloatSingle.h index 7aa2251..060cc8b 100644 --- a/LinearAlgebra/FloatSingle.h +++ b/LinearAlgebra/FloatSingle.h @@ -5,11 +5,19 @@ #ifndef FLOAT_H #define FLOAT_H +namespace Passer { +namespace LinearAlgebra { + 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 LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + #endif diff --git a/LinearAlgebra/Matrix.cpp b/LinearAlgebra/Matrix.cpp index 7a67504..b9b2eab 100644 --- a/LinearAlgebra/Matrix.cpp +++ b/LinearAlgebra/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/LinearAlgebra/Matrix.h b/LinearAlgebra/Matrix.h index 5ef0588..33087aa 100644 --- a/LinearAlgebra/Matrix.h +++ b/LinearAlgebra/Matrix.h @@ -3,6 +3,9 @@ #include "Vector3.h" +namespace Passer { +namespace LinearAlgebra { + /// @brief Single precision float matrix template class MatrixOf { public: @@ -33,7 +36,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 +46,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; @@ -111,4 +114,8 @@ private: T *data; }; +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + #endif \ No newline at end of file diff --git a/LinearAlgebra/Polar.cpp b/LinearAlgebra/Polar.cpp index f72a692..82b668b 100644 --- a/LinearAlgebra/Polar.cpp +++ b/LinearAlgebra/Polar.cpp @@ -1,84 +1,165 @@ #include -#include "Angle.h" #include "Polar.h" #include "Vector2.h" -Polar::Polar() { - angle = 0.0F; - distance = 0.0F; +template PolarOf::PolarOf() { + this->distance = 0.0f; + this->angle = AngleOf(); } - -Polar::Polar(float newAngle, float newDistance) { +template PolarOf::PolarOf(float distance, AngleOf angle) { // distance should always be 0 or greater - if (newDistance < 0) { - angle = Angle::Normalize(newAngle - 180); - distance = -newDistance; + if (distance < 0.0f) { + this->distance = -distance; + this->angle = AngleOf::Normalize(angle - AngleOf::Degrees(180)); } else { - angle = Angle::Normalize(newAngle); - distance = newDistance; + this->distance = distance; + if (this->distance == 0.0f) + // angle is always 0 if distance is 0 + this->angle = AngleOf(); + else + this->angle = AngleOf::Normalize(angle); } } -Polar::Polar(Vector2 v) { - float signY = (v.y >= 0) - (v.y < 0); - angle = atan2(v.y, signY * sqrt(v.y * v.y + v.x * v.x)) * Angle::Rad2Deg; - distance = v.magnitude(); +template +PolarOf PolarOf::Degrees(float distance, float degrees) { + AngleOf angle = AngleOf::Degrees(degrees); + PolarOf r = PolarOf(distance, angle); + return r; } -const Polar Polar::zero = Polar(0, 0); +template +PolarOf PolarOf::Radians(float distance, float radians) { + return PolarOf(distance, AngleOf::Radians(radians)); +} -float Polar::Distance(const Polar &v1, const Polar &v2) { +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) { + float distance = v.distance * cosf(v.direction.vertical.InDegrees() * + Passer::LinearAlgebra::Deg2Rad); + AngleOf angle = v.direction.horizontal; + PolarOf p = PolarOf(distance, angle); + return p; +} + +template +const PolarOf PolarOf::zero = PolarOf(0.0f, AngleOf()); +template +const PolarOf PolarOf::forward = PolarOf(1.0f, AngleOf()); +template +const PolarOf PolarOf::back = PolarOf(1.0, AngleOf::Degrees(180)); +template +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 { + return (this->distance == v.distance && + this->angle.InDegrees() == v.angle.InDegrees()); +} + +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::Degrees(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; + // angle = AngleOf::Normalize(newAngle); + // distance = newDistance; +} + +// Polar::Polar(Vector2 v) { +// float signY = (v.y >= 0) - (v.y < 0); +// angle = atan2(v.y, signY * sqrt(v.y * v.y + v.x * v.x)) * Angle::Rad2Deg; +// distance = v.magnitude(); +// } + +// 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); +// return d; +// } + +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 = AngleOf::Normalize(v.angle - this->angle).InDegrees(); + 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 = AngleOf::CosineRuleSide(v.distance, this->distance, + AngleOf::Degrees(rotation)); + + float angle = + AngleSingle::CosineRuleAngle(newDistance, this->distance, v.distance) + .InDegrees(); + + 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 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 - v1.angle); + AngleOf::CosineRuleSide(v1.distance, v2.distance, v2.angle - v1.angle); return d; } -Polar Polar::operator+(const Polar &v2) const { - if (v2.distance == 0) - return Polar(this->angle, this->distance); - if (this->distance == 0) - return v2; - - float deltaAngle = Angle::Normalize(v2.angle - this->angle); - float rotation = deltaAngle < 0 ? 180 + deltaAngle : 180 - deltaAngle; - - 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); - } - - float newDistance = - Angle::CosineRuleSide(v2.distance, this->distance, rotation); - - float angle = - Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); - - float newAngle = deltaAngle < 0 ? Angle::Normalize(this->angle - angle) - : Angle::Normalize(this->angle + angle); - Polar vector = Polar(newAngle, newDistance); - return vector; +template +PolarOf PolarOf::Rotate(const PolarOf &v, AngleOf angle) { + AngleOf a = AngleOf::Normalize(v.angle + angle); + PolarOf r = PolarOf(v.distance, a); + return r; } -Polar Polar::operator-() { - Polar vector = Polar(this->angle - 180, this->distance); - return vector; -} - -Polar Polar::operator-(const Polar &v2) const { - Polar vector = *this + (Polar(v2.angle - 180, v2.distance)); - return vector; -} - -Polar Polar::operator*(float f) const { - return Polar(this->angle, this->distance * f); -} - -Polar Polar::operator/(const float &f) { - return Polar(this->angle, this->distance / f); -} - -Polar Polar::Rotate(Polar v, float angle) { - v.angle = Angle::Normalize(v.angle + angle); - return v; -} \ No newline at end of file +template class PolarOf; +template class PolarOf; \ No newline at end of file diff --git a/LinearAlgebra/Polar.h b/LinearAlgebra/Polar.h index 6060364..e1c746f 100644 --- a/LinearAlgebra/Polar.h +++ b/LinearAlgebra/Polar.h @@ -5,98 +5,156 @@ #ifndef POLAR_H #define POLAR_H -class Vector2; +#include "Angle.h" -/// -/// A polar vector -/// -/// This will use the polar coordinate system consisting of a angle from a -/// reference direction and a distance. -struct Polar { +namespace Passer { +namespace LinearAlgebra { + +struct Vector2; +template class SphericalOf; + +template class PolarOf { public: - /// - /// The angle in degrees, clockwise rotation - /// - /// The angle is normalized to -180 .. 180 - float 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 + AngleOf angle; - /// - /// Create a new polar vector 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 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); - Polar(Vector2 v); + /// @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; - /// - /// A polar vector with zero degrees and distance - /// - const static Polar zero; + /// @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); - /// - /// Negate the polar vector. - /// + /// @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. - /// The negated vector + PolarOf operator-() const; - Polar operator-(); - /// - /// Substract a polar vector from this coordinate - /// - /// The vector to subtract from this vector - /// The result of the subtraction - Polar operator-(const Polar &v) 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); - /// - /// Add another polar vector to this polar vector - /// - /// The vector to add - /// The result of adding the vector - Polar operator+(const Polar &v) 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 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); - /// - /// 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 PolarOf &v1, const PolarOf &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(const Polar &v1, const Polar &v2); - - /// - /// Rotate the vector - /// - /// The vector to rotate - /// Angle in radias to rotate - /// The rotated vector - static Polar Rotate(Polar v, float angle); + /// @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; + +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#include "Spherical.h" +#include "Vector2.h" + #endif \ No newline at end of file diff --git a/LinearAlgebra/Quaternion.cpp b/LinearAlgebra/Quaternion.cpp index e621bb0..1a7352e 100644 --- a/LinearAlgebra/Quaternion.cpp +++ b/LinearAlgebra/Quaternion.cpp @@ -5,6 +5,7 @@ #include "Quaternion.h" #include #include +#include "Angle.h" #include "Vector3.h" void CopyQuat(const Quat& q1, Quat& q2) { @@ -117,17 +118,25 @@ 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; } -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); } @@ -144,15 +153,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(); @@ -196,8 +205,8 @@ 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.InDegrees(), axis); return rotation; } @@ -221,9 +230,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); @@ -246,7 +255,7 @@ void Quaternion::ToAxisAngleRad(const Quaternion& q, *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. @@ -297,7 +306,8 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, 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 @@ -322,9 +332,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); @@ -353,9 +363,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); @@ -394,7 +404,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/LinearAlgebra/Quaternion.h b/LinearAlgebra/Quaternion.h index eb40a5d..1979c76 100644 --- a/LinearAlgebra/Quaternion.h +++ b/LinearAlgebra/Quaternion.h @@ -7,6 +7,9 @@ #include "Vector3.h" +namespace Passer { +namespace LinearAlgebra { + extern "C" { /// /// A quaternion @@ -54,6 +57,9 @@ struct Quaternion : Quat { /// /// Quaternion(Quat q); + /// + /// Quaternion destructor + /// ~Quaternion(); /// @@ -108,7 +114,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) const; /// /// The inverse of quaterion @@ -282,4 +288,8 @@ struct Quaternion : Quat { Vector3 xyz() const; }; -#endif \ No newline at end of file +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#endif diff --git a/LinearAlgebra/README.md b/LinearAlgebra/README.md index 42397d5..35bf50f 100644 --- a/LinearAlgebra/README.md +++ b/LinearAlgebra/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/LinearAlgebra/Spherical.cpp b/LinearAlgebra/Spherical.cpp index 026d33b..e82c9af 100644 --- a/LinearAlgebra/Spherical.cpp +++ b/LinearAlgebra/Spherical.cpp @@ -1,50 +1,294 @@ #include "Spherical.h" #include "Angle.h" +#include "Quaternion.h" #include -// using Angle = float; - -Spherical::Spherical() { - this->horizontalAngle = 0; - this->verticalAngle = 0; - this->distance = 0; +template SphericalOf::SphericalOf() { + this->distance = 0.0f; + this->direction = DirectionOf(); } -// 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; - this->distance = polar.distance; +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); + } } -Spherical::Spherical(float distance, Angle horizontalAngle, Angle verticalAngle) - : distance(distance), horizontalAngle(horizontalAngle), - verticalAngle(verticalAngle) {} - -Spherical::Spherical(Vector3 v) { - float signZ = (v.z >= 0) - (v.z < 0); - horizontalAngle = - 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; - distance = v.magnitude(); +template +SphericalOf::SphericalOf(float distance, DirectionOf direction) { + if (distance < 0) { + this->distance = -distance; + this->direction = -direction; + } else { + this->distance = distance; + this->direction = direction; + } } -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); +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; } -Polar Spherical::ProjectOnHorizontalPlane() { - return Polar(horizontalAngle, distance); -} \ No newline at end of file +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; + AngleOf vertical = AngleOf(); + SphericalOf r = SphericalOf(polar.distance, horizontal, vertical); + return r; +} + +template SphericalOf SphericalOf::FromVector3(Vector3 v) { + float distance = v.magnitude(); + if (distance == 0.0f) { + return SphericalOf(distance, AngleOf(), AngleOf()); + } else { + AngleOf verticalAngle = + AngleOf::Radians((pi / 2 - acosf(v.Up() / distance))); + AngleOf horizontalAngle = + AngleOf::Radians(atan2f(v.Right(), v.Forward())); + return SphericalOf(distance, horizontalAngle, verticalAngle); + } +} + +/** + * @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(); + + 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 v; +} + +template +const SphericalOf SphericalOf::zero = + SphericalOf(0.0f, AngleOf(), AngleOf()); +template +const SphericalOf SphericalOf::forward = + SphericalOf(1.0f, AngleOf(), AngleOf()); +template +const SphericalOf SphericalOf::back = + SphericalOf(1.0f, AngleOf::Degrees(180), AngleOf()); +template +const SphericalOf SphericalOf::right = + SphericalOf(1.0f, AngleOf::Degrees(90), AngleOf()); +template +const SphericalOf SphericalOf::left = + SphericalOf(1.0f, AngleOf::Degrees(-90), AngleOf()); +template +const SphericalOf SphericalOf::up = + SphericalOf(1.0f, AngleOf(), AngleOf::Degrees(90)); +template +const SphericalOf SphericalOf::down = + SphericalOf(1.0f, AngleOf(), AngleOf::Degrees(-90)); + +template +SphericalOf SphericalOf::WithDistance(float distance) { + SphericalOf v = SphericalOf(distance, this->direction); + return SphericalOf(); +} + +template SphericalOf SphericalOf::operator-() const { + SphericalOf v = SphericalOf( + this->distance, this->direction.horizontal + AngleOf::Degrees(180), + this->direction.vertical + AngleOf::Degrees(180)); + 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 SphericalOf SphericalOf::operator*=(float f) { + this->distance *= f; + return *this; +} + +template SphericalOf SphericalOf::operator/=(float f) { + this->distance /= f; + return *this; +} + +#include "FloatSingle.h" +#include "Vector3.h" + +const float epsilon = 1E-05f; + +template +float SphericalOf::DistanceBetween(const SphericalOf &v1, + const SphericalOf &v2) { + // SphericalOf difference = v1 - v2; + // return difference.distance; + Vector3 vec1 = v1.ToVector3(); + Vector3 vec2 = v2.ToVector3(); + float distance = Vector3::Distance(vec1, vec2); + return distance; +} + +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; + AngleSingle r = Vector3::Angle(v1_3, v2_3); + 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(); + AngleSingle r = Vector3::SignedAngle(v1_vector, v2_vector, axis_vector); + return AngleOf::Degrees(r.InDegrees()); +} + +template +SphericalOf SphericalOf::Rotate(const SphericalOf &v, + AngleOf horizontalAngle, + AngleOf 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.direction.horizontal + a, v.direction.vertical); + return r; +} +template +SphericalOf SphericalOf::RotateVertical(const SphericalOf &v, + AngleOf a) { + SphericalOf r = + SphericalOf(v.distance, v.direction.horizontal, v.direction.vertical + a); + return r; +} + +template class SphericalOf; +template class SphericalOf; diff --git a/LinearAlgebra/Spherical.h b/LinearAlgebra/Spherical.h index 7c98263..4d803bd 100644 --- a/LinearAlgebra/Spherical.h +++ b/LinearAlgebra/Spherical.h @@ -1,66 +1,188 @@ -/// @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/. +// 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 -#include "Angle.h" -#include "Polar.h" - -struct Vector3; +#include "Direction.h" namespace Passer { +namespace LinearAlgebra { -/// @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 { +struct Vector3; +template class PolarOf; + +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 - Angle horizontalAngle; + // AngleOf horizontal; /// @brief The angle in the vertical plane in degrees. Positive is upward. /// @details The angle is automatically normalized to -180 .. 180 - Angle verticalAngle; + // AngleOf vertical; + DirectionOf direction; - /// @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 + SphericalOf(); + 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 - // Spherical(float polarAngle, float elevationAngle, float distance); + /// @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; - Spherical(float distance, Angle horizontalAngle, Angle verticalAngle); + /// @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 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 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 - const static Spherical zero; + 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; - float GetSwing(); + /// @brief Update the distance component of the spherical coordinate + /// @param distance The new distance + /// @return The updated coordinate + SphericalOf WithDistance(float distance); - Polar ProjectOnHorizontalPlane(); + /// @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); + + /// @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.direction); + } + friend SphericalOf operator*(float f, const SphericalOf &v) { + return SphericalOf(f * v.distance, v.direction); + } + 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.direction); + } + friend SphericalOf operator/(float f, const SphericalOf &v) { + return SphericalOf(f / v.distance, v.direction); + } + 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); }; -} // namespace Passer -using namespace Passer; +/// @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 +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#include "Polar.h" #include "Vector3.h" #endif \ No newline at end of file diff --git a/LinearAlgebra/SwingTwist.cpp b/LinearAlgebra/SwingTwist.cpp new file mode 100644 index 0000000..58905c7 --- /dev/null +++ b/LinearAlgebra/SwingTwist.cpp @@ -0,0 +1,168 @@ +// 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->swing = DirectionOf(AngleOf(), AngleOf()); + this->twist = AngleOf(); +} + +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; +} + +template +SwingTwistOf::SwingTwistOf(AngleOf horizontal, + AngleOf vertical, + AngleOf twist) { + // 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; +} + +template +SwingTwistOf SwingTwistOf::Degrees(float horizontal, + float vertical, + float twist) { + 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; +} + +template +Quaternion SwingTwistOf::ToQuaternion() const { + Quaternion q = Quaternion::Euler(-this->swing.vertical.InDegrees(), + this->swing.horizontal.InDegrees(), + this->twist.InDegrees()); + return q; +} + +template +SwingTwistOf SwingTwistOf::FromQuaternion(Quaternion q) { + Vector3 angles = Quaternion::ToAngles(q); + SwingTwistOf r = + SwingTwistOf::Degrees(angles.Up(), angles.Right(), angles.Forward()); + r.Normalize(); + return r; +} + +template +SphericalOf 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 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(); + +template +SphericalOf SwingTwistOf::operator*(const SphericalOf& vector) const { + SphericalOf v = SphericalOf( + vector.distance, vector.direction.horizontal + this->swing.horizontal, + vector.direction.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->twist += rotation.twist; + return *this; +} + +template +SwingTwistOf SwingTwistOf::Inverse(SwingTwistOf rotation) { + SwingTwistOf r = SwingTwistOf( + -rotation.swing.horizontal, -rotation.swing.vertical, -rotation.twist); + return r; +} + +template +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); + 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 +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/LinearAlgebra/SwingTwist.h b/LinearAlgebra/SwingTwist.h new file mode 100644 index 0000000..7fac16a --- /dev/null +++ b/LinearAlgebra/SwingTwist.h @@ -0,0 +1,78 @@ +// 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 "Angle.h" +#include "Direction.h" +#include "Quaternion.h" +#include "Spherical.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() const; + static SwingTwistOf FromQuaternion(Quaternion q); + + SphericalOf ToAngleAxis() const; + static SwingTwistOf FromAngleAxis(SphericalOf aa); + + const static SwingTwistOf identity; + + bool operator==(const SwingTwistOf d) const; + + /// + /// 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 DirectionOf& axis); + + static AngleOf Angle(const SwingTwistOf& r1, const SwingTwistOf& r2); + + void Normalize(); +}; + +using SwingTwistSingle = SwingTwistOf; +using SwingTwist16 = SwingTwistOf; + +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#endif diff --git a/LinearAlgebra/Vector2.cpp b/LinearAlgebra/Vector2.cpp index 150b12f..094601e 100644 --- a/LinearAlgebra/Vector2.cpp +++ b/LinearAlgebra/Vector2.cpp @@ -5,26 +5,37 @@ #include "Vector2.h" #include "Angle.h" #include "FloatSingle.h" +#include "Vector3.h" -#if defined(AVR) -#include -#else +// #if defined(AVR) +// #include +// #else #include -#endif +// #endif 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.Right(); // x; + y = v.Forward(); // z; +} +Vector2::Vector2(PolarSingle p) { + float horizontalRad = p.angle.InDegrees() * Passer::LinearAlgebra::Deg2Rad; + float cosHorizontal = cosf(horizontalRad); + float sinHorizontal = sinf(horizontalRad); -Vector2::Vector2(Vec2 v) { - x = v.x; - y = v.y; + x = p.distance * sinHorizontal; + y = p.distance * cosHorizontal; } Vector2::~Vector2() {} @@ -38,15 +49,18 @@ const Vector2 Vector2::down = Vector2(0, -1); const Vector2 Vector2::forward = Vector2(0, 1); const Vector2 Vector2::back = Vector2(0, -1); -float Vector2::Magnitude(const Vector2 &a) { - return sqrtf(a.x * a.x + a.y * a.y); +bool Vector2::operator==(const Vector2 &v) { + return (this->x == v.x && this->y == v.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(Vector2 v) { +Vector2 Vector2::Normalize(const Vector2 &v) { float num = Vector2::Magnitude(v); Vector2 result = Vector2::zero; if (num > Float::epsilon) { @@ -63,56 +77,65 @@ Vector2 Vector2::normalized() const { return result; } -Vector2 Vector2::ClampMagnitude(const Vector2 &v, float magnitude) { - float length = Vector2::Magnitude(v); - Vector2 r = v; - if (length > magnitude) - r = v / (length * magnitude); - - return r; -} - -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); +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::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::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 Vector2::operator/(const float &d) const { - return Vector2(this->x / d, this->y / d); +// 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) { 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 &v1, const Vector2 &v2) { + return Magnitude(v1 - v2); } -float Vector2::Distance(const Vector2 &p1, const Vector2 &p2) { - return Magnitude(p1 - p2); +float Vector2::Angle(const Vector2 &v1, const Vector2 &v2) { + return (float)fabs(SignedAngle(v1, v2)); } - -float Vector2::Angle(Vector2 from, Vector2 to) { - return (float)fabs(SignedAngle(from, to)); -} - -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; @@ -123,13 +146,14 @@ float Vector2::SignedAngle(Vector2 from, Vector2 to) { return nanf(""); #endif - float angleFrom = atan2(from.y, from.x); - float angleTo = atan2(to.y, to.x); - return (angleTo - angleFrom) * Angle::Rad2Deg; + float angleFrom = atan2f(v1.y, v1.x); + float angleTo = atan2f(v2.y, v2.x); + return -(angleTo - angleFrom) * Passer::LinearAlgebra::Rad2Deg; } -Vector2 Vector2::Rotate(Vector2 v, float angle) { - float angleRad = angle * Angle::Deg2Rad; +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); @@ -140,16 +164,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, float f) { + Vector2 v = v1 + (v2 - v1) * f; return v; } - -float Vector2::ToFactor(Vector2 a, Vector2 b) { - return (1 - Vector2::Dot(a, b)) / 2; -} diff --git a/LinearAlgebra/Vector2.h b/LinearAlgebra/Vector2.h index c2b0d11..eabac98 100644 --- a/LinearAlgebra/Vector2.h +++ b/LinearAlgebra/Vector2.h @@ -5,6 +5,8 @@ #ifndef VECTOR2_H #define VECTOR2_H +#include "Angle.h" + extern "C" { /// /// 2-dimensional Vector representation @@ -24,215 +26,186 @@ typedef struct Vec2 { } Vec2; } -/// -/// A 2-dimensional vector -/// -/// 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); +namespace Passer { +namespace LinearAlgebra { +struct Vector3; +template class PolarOf; +// using Polar = PolarOf + +/// @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 { + friend struct Vec2; + +public: + /// @brief A new 2-dimensional zero vector + Vector2(); + /// @brief A new 2-dimensional vector + /// @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 + Vector2(Vector3 v); + /// @brief Convert a Polar vector to a 2-dimensional vector + /// @param v The vector in polar coordinates + Vector2(PolarOf v); + + /// @brief Vector2 destructor ~Vector2(); - /// - /// 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) - /// - /// - 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) - /// + /// @brief A normalized forward-oriented vector const static Vector2 forward; - /// - /// A vector with values (0, -1) - /// + /// @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 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; - /// - /// 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 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 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); + /// @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(const Vector2 &v); + /// @brief Convert the vector to a length 1 + /// @return The vector normalized to a length of 1 Vector2 normalized() const; - static Vector2 ClampMagnitude(const Vector2 &v, float magnitude); - - /// - /// 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; + 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); - /// - /// 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) 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 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) { + 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) { + 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); - /// - /// 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); - /// - /// 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); + /// @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); - /// - /// 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 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 - /// - /// 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 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::AngleSingle a); - /// - /// 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); - - /// - /// 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); + /// @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, float f); }; +} // namespace LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#include "Polar.h" + #endif \ No newline at end of file diff --git a/LinearAlgebra/Vector3.cpp b/LinearAlgebra/Vector3.cpp index c08c1c0..8a63923 100644 --- a/LinearAlgebra/Vector3.cpp +++ b/LinearAlgebra/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; @@ -10,21 +13,40 @@ 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(SphericalOf s) { + float verticalRad = (90.0f - s.direction.vertical.InDegrees()) * + Passer::LinearAlgebra::Deg2Rad; + float horizontalRad = + s.direction.horizontal.InDegrees() * Passer::LinearAlgebra::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() {} @@ -41,17 +63,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); } @@ -72,38 +94,67 @@ 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::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 Vector3::operator/(float d) const { - return Vector3(this->x / d, this->y / d, this->z / d); +// 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; } 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); } -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) { @@ -111,25 +162,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; } @@ -139,37 +184,38 @@ 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()); +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(from, to); + 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 r; + float r = ((float)acos(cdot)); + return AngleOf::Radians(r); } -float Vector3::SignedAngle(const Vector3 &from, const Vector3 &to, - const Vector3 &axis) { +AngleOf Vector3::SignedAngle(const Vector3 &v1, const Vector3 &v2, + const Vector3 &axis) { // angle in [0,180] - float angle = Vector3::Angle(from, to); + AngleOf 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); // 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 &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/LinearAlgebra/Vector3.h b/LinearAlgebra/Vector3.h index 50fc1f3..9839659 100644 --- a/LinearAlgebra/Vector3.h +++ b/LinearAlgebra/Vector3.h @@ -7,6 +7,12 @@ #include "Vector2.h" +namespace Passer { +namespace LinearAlgebra { + +// struct Spherical; +template class SphericalOf; + extern "C" { /// /// 3-dimensional Vector representation @@ -14,6 +20,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 /// @@ -30,242 +37,198 @@ 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); + /// @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(SphericalOf 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 - /// - const static Vector3 right; - /// - /// A normalized vector pointing in the left direction - /// - const static Vector3 left; - /// - /// A normalized vector pointing in the upward direction - /// - const static Vector3 up; - /// - /// A normalized vector pointing in the downward direcion - /// - 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; + /// @brief A normalized right-oriented vector + const static Vector3 right; + /// @brief A normalized left-oriented vector + const static Vector3 left; + /// @brief A normalized up-oriented vector + const static Vector3 up; + /// @brief A normalized down-oriented vector + const static Vector3 down; - // 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) const; + + /// @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, 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) { + 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); - /// - /// 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); + /// @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 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 AngleOf SignedAngle(const Vector3 &v1, const Vector3 &v2, + const Vector3 &axis); - /// - /// 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, - 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 LinearAlgebra +} // namespace Passer +using namespace Passer::LinearAlgebra; + +#include "Spherical.h" + #endif \ No newline at end of file diff --git a/LinearAlgebra/test/Angle16_test.cc b/LinearAlgebra/test/Angle16_test.cc new file mode 100644 index 0000000..16d8451 --- /dev/null +++ b/LinearAlgebra/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_FLOAT_EQ(r.InDegrees(), 0) << "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/LinearAlgebra/test/Angle8_test.cc b/LinearAlgebra/test/Angle8_test.cc new file mode 100644 index 0000000..158694f --- /dev/null +++ b/LinearAlgebra/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_FLOAT_EQ(r.InDegrees(), 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/LinearAlgebra/test/AngleSingle_test.cc b/LinearAlgebra/test/AngleSingle_test.cc new file mode 100644 index 0000000..773dfe4 --- /dev/null +++ b/LinearAlgebra/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) { + AngleSingle 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) { + AngleSingle 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(), 0) << "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) { +// AngleSingle 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/LinearAlgebra/test/Angle_test.cc b/LinearAlgebra/test/Angle_test.cc deleted file mode 100644 index 77ec3b6..0000000 --- a/LinearAlgebra/test/Angle_test.cc +++ /dev/null @@ -1,167 +0,0 @@ -#if GTEST -#include - -#include -#include - -#include "Angle.h" - -#define FLOAT_INFINITY std::numeric_limits::infinity() - -TEST(Angle, Normalize) { - float r = 0; - - 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+360); - EXPECT_FLOAT_EQ(r, -90) << "Normalize 270+360"; - - 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(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"; - - r = Angle::Normalize(-FLOAT_INFINITY); - EXPECT_FLOAT_EQ(r, -FLOAT_INFINITY) << "Normalize INFINITY"; - } -} - -TEST(Angle, Clamp) { - 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, 0) << "Clamp -1 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(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"; - - 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"; - } -} - -TEST(Angle, Difference) { - 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, 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(0, 0); - EXPECT_FLOAT_EQ(r, 0) << "Difference 0 0"; - - 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"; - - 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"; - } -} - -TEST(Angle, MoveTowards) { - float r = 0; - - 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, 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, -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, -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, 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, 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"; - - 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, -FLOAT_INFINITY, -30); - EXPECT_FLOAT_EQ(r, 30) << "MoveTowards 0 -FLOAT_INFINITY -30"; - } -} - -#endif \ No newline at end of file diff --git a/LinearAlgebra/test/Direction_test.cc b/LinearAlgebra/test/Direction_test.cc new file mode 100644 index 0000000..461140c --- /dev/null +++ b/LinearAlgebra/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 diff --git a/LinearAlgebra/test/DiscreteAngle_test.cc b/LinearAlgebra/test/DiscreteAngle_test.cc new file mode 100644 index 0000000..91a7cc8 --- /dev/null +++ b/LinearAlgebra/test/DiscreteAngle_test.cc @@ -0,0 +1,82 @@ +/* +#if GTEST +#include + +#include +#include + +#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::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); + + angle = -180.0F; + a = Angle8::Degrees(angle); + EXPECT_FLOAT_EQ(a.InDegrees(), angle); +} + +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(Angle16, Construct) { + Angle16 a = Angle16::Degrees(0.0F); + EXPECT_FLOAT_EQ(a.InDegrees(), 0); +} + +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); +} + +#endif +*/ \ No newline at end of file diff --git a/LinearAlgebra/test/FloatSingle_test.cc b/LinearAlgebra/test/FloatSingle_test.cc index 3083985..9673ade 100644 --- a/LinearAlgebra/test/FloatSingle_test.cc +++ b/LinearAlgebra/test/FloatSingle_test.cc @@ -1,41 +1,41 @@ #if GTEST #include -#include #include +#include #include "FloatSingle.h" #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, 0) << "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/LinearAlgebra/test/Matrix_test.cc b/LinearAlgebra/test/Matrix_test.cc index dd358f9..a1267cf 100644 --- a/LinearAlgebra/test/Matrix_test.cc +++ b/LinearAlgebra/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/LinearAlgebra/test/Polar_test.cc b/LinearAlgebra/test/Polar_test.cc new file mode 100644 index 0000000..9e244f2 --- /dev/null +++ b/LinearAlgebra/test/Polar_test.cc @@ -0,0 +1,232 @@ +#if GTEST +#include +#include +#include + +#include "Polar.h" +#include "Spherical.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Polar, FromVector2) { + Vector2 v = Vector2(0, 1); + 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 = 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 = 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"; +} + +TEST(Polar, FromSpherical) { + SphericalSingle s; + PolarSingle p; + + 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 = 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 = 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 = 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 = 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 = 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) { + 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 == PolarSingle(2, AngleSingle::Degrees(-135))) + << "Negate(2 45)"; + + v = PolarSingle::Deg(2, -45); + r = -v; + EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(135))) + << "Negate(2 -45)"; + + v = PolarSingle::Degrees(2, 0); + r = -v; + EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(180))) << "Negate(2 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 == PolarSingle(0, AngleSingle::Degrees(0))) << "Negate(0 0)"; +} + +TEST(Polar, Subtraction) { + 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 = PolarSingle::zero; + r = v1 - v2; + EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Subtraction(0 0)"; +} + +TEST(Polar, Addition) { + 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 = PolarSingle::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)"; + + 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) { + 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)"; + EXPECT_FLOAT_EQ(r.angle.InDegrees(), v1.angle.InDegrees()) + << "ScaleMult(4 45, 2)"; +} + +TEST(Polar, Scale_Divide) { + 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)"; + EXPECT_FLOAT_EQ(r.angle.InDegrees(), v1.angle.InDegrees()) + << "ScaleDiv(4 45, 2)"; +} + +TEST(Polar, Distance) { + PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); + PolarSingle v2 = PolarSingle(1, AngleSingle::Degrees(-90)); + float d = 0; + + d = PolarSingle::Distance(v1, v2); + // don't know what to expect yet + + v2 = PolarSingle::zero; + d = PolarSingle::Distance(v1, v2); + EXPECT_FLOAT_EQ(d, v1.distance) << "Distance(4 45, zero)"; +} + +TEST(Polar, Rotate) { + PolarSingle v = PolarSingle(4, AngleSingle::Degrees(45)); + PolarSingle r = PolarSingle::zero; + + 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)"; +} + +// 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(), -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 +} + +#endif \ No newline at end of file diff --git a/LinearAlgebra/test/Spherical16_test.cc b/LinearAlgebra/test/Spherical16_test.cc new file mode 100644 index 0000000..789a8c7 --- /dev/null +++ b/LinearAlgebra/test/Spherical16_test.cc @@ -0,0 +1,222 @@ +#if GTEST +#include +#include +#include + +#include "Spherical.h" +#include "Vector3.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Spherical16, FromVector3) { + Vector3 v = Vector3(0, 0, 1); + Spherical16 s = Spherical16::FromVector3(v); + + EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 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.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.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, 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); + +// 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)"; + +// 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.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.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.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.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, Angle16::Degrees(98.18f), Angle16::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); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-02); + + 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"; +} + +TEST(Spherical16, Incident2) { + Vector3 v = Vector3(1.0f, 0.0f, 1.0f); + Spherical16 s = Spherical16::FromVector3(v); + + 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.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.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(0.0f, 1.0f, 1.0f); + s = Spherical16::FromVector3(v); + + sr = Spherical16(1.4142135623F, Angle16::Degrees(0), Angle16::Degrees(45)); + EXPECT_NEAR(s.distance, sr.distance, 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.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.direction.horizontal, s.direction.vertical) + .ToVector3(); + + EXPECT_NEAR(s.distance, 1.73205080F, 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); + 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, Angle16::Degrees(45), Angle16::Degrees(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, Angle16::Degrees(-45), Angle16::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 = 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.direction.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; + 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/LinearAlgebra/test/SphericalSingle_test.cc b/LinearAlgebra/test/SphericalSingle_test.cc new file mode 100644 index 0000000..7840d77 --- /dev/null +++ b/LinearAlgebra/test/SphericalSingle_test.cc @@ -0,0 +1,213 @@ +#if GTEST +#include +#include +#include + +#include "Spherical.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(SphericalSingle, FromVector3) { + Vector3 v = Vector3(0, 0, 1); + 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 = 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 = 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(SphericalSingle, FromPolar) { + PolarSingle p = PolarSingle(1, AngleSingle::Degrees(0)); + 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) + << "s.hor Polar(1 0)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(1 0)"; + + p = PolarSingle(1, AngleSingle::Degrees(45)); + 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) + << "s.hor Polar(1 45)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(1 45)"; + + p = PolarSingle(1, AngleSingle::Degrees(-45)); + 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) + << "s.hor Polar(1 -45)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(1 -45)"; + + p = PolarSingle(0, AngleSingle::Degrees(0)); + 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) + << "s.hor Polar(0 0)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(0 0)"; + + p = PolarSingle(-1, AngleSingle::Degrees(0)); + 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) + << "s.hor Polar(-1 0)"; + EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) + << "s.vert Polar(-1 0)"; +} + +TEST(SphericalSingle, Incident1) { + Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); + SphericalSingle s = SphericalSingle ::FromVector3(v); + + 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); + 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"; + 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(SphericalSingle, Incident2) { + Vector3 v = Vector3(1.0f, 0.0f, 1.0f); + SphericalSingle s = SphericalSingle ::FromVector3(v); + + 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); + 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); + 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 = SphericalSingle ::FromVector3(v); + + 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); + 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); + 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 = SphericalSingle ::FromVector3(v); + r = Vector3(s); + + EXPECT_NEAR(s.distance, 1.73205080F, 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); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); + + // 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(SphericalSingle, Addition) { + SphericalSingle v1 = + SphericalSingle(1, AngleSingle::Degrees(45), AngleSingle::Degrees(0)); + SphericalSingle v2 = SphericalSingle ::zero; + SphericalSingle r = SphericalSingle ::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 = 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, 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)"; + 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 diff --git a/LinearAlgebra/test/SwingTwistSingle_test.cc b/LinearAlgebra/test/SwingTwistSingle_test.cc new file mode 100644 index 0000000..8885ae4 --- /dev/null +++ b/LinearAlgebra/test/SwingTwistSingle_test.cc @@ -0,0 +1,131 @@ +#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"; +} + +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"; + + 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"; +} + +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 diff --git a/LinearAlgebra/test/Vector2_test.cc b/LinearAlgebra/test/Vector2_test.cc index 83c52ce..3afeb4b 100644 --- a/LinearAlgebra/test/Vector2_test.cc +++ b/LinearAlgebra/test/Vector2_test.cc @@ -7,6 +7,33 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() +TEST(Vector2, FromPolar) { + Vector2 v; + PolarSingle p; + Vector2 r; + + v = Vector2(0, 1); + 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 = 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 = PolarSingle::FromVector2(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; @@ -99,8 +126,6 @@ TEST(Vector2, Normalize) { } TEST(Vector2, Negate) { - bool r = false; - Vector2 v1 = Vector2(4, 5); Vector2 v = Vector2::zero; @@ -129,8 +154,6 @@ TEST(Vector2, Negate) { } TEST(Vector2, Subtract) { - bool r = false; - Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 v = Vector2::zero; @@ -145,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; @@ -164,11 +193,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"; @@ -176,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); @@ -195,8 +227,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 +256,6 @@ TEST(Vector2, Scale) { } TEST(Vector2, Multiply) { - bool r = false; - Vector2 v1 = Vector2(4, 5); float f = 3; Vector2 v = Vector2::zero; @@ -257,8 +285,6 @@ TEST(Vector2, Multiply) { } TEST(Vector2, Divide) { - bool r = false; - Vector2 v1 = Vector2(4, 5); float f = 2; Vector2 v = Vector2::zero; @@ -399,11 +425,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,22 +446,32 @@ 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) { Vector2 v1 = Vector2(1, 2); Vector2 r = Vector2(0, 0); - r = Vector2::Rotate(v1, 0); + r = Vector2::Rotate(v1, AngleSingle::Degrees(0)); EXPECT_FLOAT_EQ(Vector2::Distance(r, v1), 0); - r = Vector2::Rotate(v1, 180); + r = Vector2::Rotate(v1, AngleSingle::Degrees(180)); EXPECT_NEAR(Vector2::Distance(r, Vector2(-1, -2)), 0, 1.0e-06); - r = Vector2::Rotate(v1, -90); + r = Vector2::Rotate(v1, AngleSingle::Degrees(-90)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); - r = Vector2::Rotate(v1, 270); + r = Vector2::Rotate(v1, AngleSingle::Degrees(270)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); } @@ -460,6 +496,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 diff --git a/LinearAlgebra/test/Vector3_test.cc b/LinearAlgebra/test/Vector3_test.cc index e8f61f8..82e57e9 100644 --- a/LinearAlgebra/test/Vector3_test.cc +++ b/LinearAlgebra/test/Vector3_test.cc @@ -7,6 +7,32 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() +TEST(Vector3, FromSpherical) { + Vector3 v = Vector3(0, 0, 1); + SphericalOf s = SphericalOf::FromVector3(v); + Vector3 r = Vector3(s); + + 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 = SphericalOf::FromVector3(v); + r = Vector3(s); + + 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 = SphericalOf::FromVector3(v); + r = Vector3(s); + + 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) { Vector3 v = Vector3(1, 2, 3); float m = 0; @@ -92,19 +118,17 @@ 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"; } } TEST(Vector3, Negate) { - bool r = false; - Vector3 v1 = Vector3(4, 5, 6); Vector3 v = Vector3::zero; @@ -133,8 +157,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 +190,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 +219,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 +248,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 +277,6 @@ TEST(Vector3, Multiply) { } TEST(Vector3, Divide) { - bool r = false; - Vector3 v1 = Vector3(4, 5, 6); float f = 2; Vector3 v = Vector3::zero; @@ -395,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)"; } } @@ -428,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)"; } } @@ -461,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)"; } } @@ -474,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 = AngleOf::Degrees(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.InDegrees(), 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.InDegrees(), 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.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); + 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); + r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "Angle(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -505,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 = AngleOf::Degrees(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.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, 167.066864F) << "SignedAngle(4 5 6, -1 -2 -3, 7 8 -9)"; + 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, 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, 12.9331388F) << "SignedAngle(4 5 6, 1 2 3, -7 -8 9)"; + 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, 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); + 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); + r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "SignedAngle(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -562,4 +579,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