Moved Polar/Spherical to template class completely

This commit is contained in:
Pascal Serrarens 2024-08-28 11:32:37 +02:00
parent e0ef43a699
commit f48343952b
12 changed files with 407 additions and 127 deletions

156
Polar.cpp
View File

@ -1,9 +1,155 @@
#include <math.h>
#include "Angle.h"
#include "Polar.h"
#include "Spherical.h"
template <typename T>
PolarOf<T>::PolarOf() {
this->distance = 0.0f;
this->angle = 0.0f;
}
template <typename T>
PolarOf<T>::PolarOf(float distance, AngleOf<T> angle) {
// distance should always be 0 or greater
if (distance < 0.0f) {
this->distance = -distance;
this->angle = AngleOf<T>::Normalize(angle.ToFloat() - 180.0f);
} else {
this->distance = distance;
if (this->distance == 0.0f)
// angle is always 0 if distance is 0
this->angle = 0.0f;
else
this->angle = AngleOf<T>::Normalize(angle);
}
}
template <typename T>
PolarOf<T> PolarOf<T>::FromVector2(Vector2 v) {
float distance = v.magnitude();
AngleOf<T> angle = Vector2::SignedAngle(Vector2::forward, v);
PolarOf<T> p = PolarOf(distance, angle);
return p;
}
template <typename T>
PolarOf<T> PolarOf<T>::FromSpherical(SphericalOf<T> v) {
float distance =
v.distance * cosf(v.vertical.ToFloat() * Passer::LinearAlgebra::Deg2Rad);
AngleOf<T> angle = v.horizontal;
PolarOf<T> p = PolarOf(distance, angle);
return p;
}
template <typename T>
const PolarOf<T> PolarOf<T>::zero = PolarOf(0.0f, 0.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::forward = PolarOf(1.0f, 0.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::back = PolarOf(1.0, 180.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::right = PolarOf(1.0, 90.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::left = PolarOf(1.0, -90.0f);
template <typename T>
bool PolarOf<T>::operator==(const PolarOf& v) const {
return (this->distance == v.distance &&
this->angle.ToFloat() == v.angle.ToFloat());
}
template <typename T>
PolarOf<T> PolarOf<T>::Normalize(const PolarOf& v) {
PolarOf<T> r = PolarOf(1, v.angle);
return r;
}
template <typename T>
PolarOf<T> PolarOf<T>::normalized() const {
PolarOf<T> r = PolarOf(1, this->angle);
return r;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator-() const {
PolarOf<T> v = PolarOf(this->distance, this->angle + AngleOf<T>(180));
return v;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator-(const PolarOf& v) const {
PolarOf<T> r = -v;
return *this + r;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator-=(const PolarOf& v) {
*this = *this - v;
return *this;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator+(const PolarOf& v) const {
if (v.distance == 0)
return PolarOf(this->distance, this->angle);
if (this->distance == 0.0f)
return v;
float deltaAngle =
Angle::Normalize(v.angle.ToFloat() - this->angle.ToFloat()).ToFloat();
float rotation =
deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle;
if (rotation == 180.0f && v.distance > 0.0f) {
// angle is too small, take this angle and add the distances
return PolarOf(this->distance + v.distance, this->angle);
}
float newDistance =
Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat();
float angle =
Angle::CosineRuleAngle(newDistance, this->distance, v.distance).ToFloat();
float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle
: this->angle.ToFloat() + angle;
newAngle = Angle::Normalize(newAngle).ToFloat();
PolarOf vector = PolarOf(newDistance, newAngle);
return vector;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator+=(const PolarOf& v) {
*this = *this + v;
return *this;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator*=(float f) {
this->distance *= f;
return *this;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator/=(float f) {
this->distance /= f;
return *this;
}
template <typename T>
float PolarOf<T>::Distance(const PolarOf& v1, const PolarOf& v2) {
float d = Angle::CosineRuleSide(v1.distance, v2.distance,
v2.angle.ToFloat() - v1.angle.ToFloat())
.ToFloat();
return d;
}
template <typename T>
PolarOf<T> PolarOf<T>::Rotate(const PolarOf& v, AngleOf<T> angle) {
AngleOf<T> a = AngleOf<T>::Normalize(v.angle + angle);
PolarOf<T> r = PolarOf(v.distance, a);
return r;
}
template class PolarOf<float>;
template class PolarOf<signed short>;
//=====================================
/*
Polar::Polar() {
this->distance = 0.0f;
this->angle = 0.0f;
@ -85,7 +231,8 @@ Polar Polar::operator+(const Polar& v) const {
Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat();
float angle =
Angle::CosineRuleAngle(newDistance, this->distance, v.distance).ToFloat();
Angle::CosineRuleAngle(newDistance, this->distance,
v.distance).ToFloat();
float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle
: this->angle.ToFloat() + angle;
@ -130,4 +277,5 @@ Polar Polar::Rotate(const Polar& v, Angle angle) {
Angle a = Angle::Normalize(v.angle.ToFloat() + angle.ToFloat());
Polar r = Polar(v.distance, a);
return r;
}
}
*/

126
Polar.h
View File

@ -11,8 +11,130 @@ namespace Passer {
namespace LinearAlgebra {
struct Vector2;
struct Spherical;
template <typename T>
class SphericalOf;
template <typename T>
class PolarOf {
public:
/// @brief The distance in meters
/// @remark The distance shall never be negative
float distance;
/// @brief The angle in degrees clockwise rotation
/// @remark The angle shall be between -180 .. 180
AngleOf<T> angle;
/// @brief A new vector with polar coordinates with zero degrees and
/// distance
PolarOf();
/// @brief A new vector with polar coordinates
/// @param distance The distance in meters
/// @param angle The angle in degrees, clockwise rotation
/// @note The distance is automatically converted to a positive value.
/// @note The angle is automatically normalized to -180 .. 180
PolarOf(float distance, AngleOf<T> angle);
/// @brief Convert a vector from 2D carthesian coordinates to polar
/// coordinates
/// @param v The vector to convert
static PolarOf<T> 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<T> FromSpherical(SphericalOf<T> v);
/// @brief A polar vector with zero degrees and distance
const static PolarOf zero;
/// @brief A normalized forward-oriented vector
const static PolarOf forward;
/// @brief A normalized back-oriented vector
const static PolarOf back;
/// @brief A normalized right-oriented vector
const static PolarOf right;
/// @brief A normalized left-oriented vector
const static PolarOf left;
/// @brief Equality test to another vector
/// @param v The vector to check against
/// @return true: if it is identical to the given vector
/// @note This uses float comparison to check equality which may have
/// strange effects. Equality on floats should be avoided.
bool operator==(const PolarOf& v) const;
/// @brief The vector length
/// @param v The vector for which you need the length
/// @return The vector length;
inline static float Magnitude(const PolarOf& v) { return v.distance; }
/// @brief The vector length
/// @return The vector length
inline float magnitude() const { return this->distance; }
/// @brief Convert the vector to a length of 1
/// @param v The vector to convert
/// @return The vector normalized to a length of 1
static PolarOf Normalize(const PolarOf& v);
/// @brief Convert the vector to a length of a
/// @return The vector normalized to a length of 1
PolarOf normalized() const;
/// @brief Negate the vector
/// @return The negated vector
/// This will rotate the vector by 180 degrees. Distance will stay the same.
PolarOf operator-() const;
/// @brief Subtract a polar vector from this vector
/// @param v The vector to subtract
/// @return The result of the subtraction
PolarOf operator-(const PolarOf& v) const;
PolarOf operator-=(const PolarOf& v);
/// @brief Add a polar vector to this vector
/// @param v The vector to add
/// @return The result of the addition
PolarOf operator+(const PolarOf& v) const;
PolarOf operator+=(const PolarOf& v);
/// @brief Scale the vector uniformly up
/// @param f The scaling factor
/// @return The scaled vector
/// @remark This operation will scale the distance of the vector. The angle
/// will be unaffected.
friend PolarOf operator*(const PolarOf& v, float f) {
return PolarOf(v.distance * f, v.angle);
}
friend PolarOf operator*(float f, const PolarOf& v) {
return PolarOf(f * v.distance, v.angle);
}
PolarOf operator*=(float f);
/// @brief Scale the vector uniformly down
/// @param f The scaling factor
/// @return The scaled factor
/// @remark This operation will scale the distance of the vector. The angle
/// will be unaffected.
friend PolarOf operator/(const PolarOf& v, float f) {
return PolarOf(v.distance / f, v.angle);
}
friend PolarOf operator/(float f, const PolarOf& v) {
return PolarOf(f / v.distance, v.angle);
}
PolarOf operator/=(float f);
/// @brief The distance between two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The distance between the two vectors
static float Distance(const PolarOf& v1, const PolarOf& v2);
/// @brief Rotate a vector
/// @param v The vector to rotate
/// @param a The angle in degreesto rotate
/// @return The rotated vector
static PolarOf Rotate(const PolarOf& v, AngleOf<T> a);
};
using PolarSingle = PolarOf<float>;
using Polar16 = PolarOf<signed short>;
using Polar = PolarSingle;
/*
/// @brief A polar vector
/// @details This will use the polar coordinate system consisting of a angle
/// from a reference direction and a distance.
@ -130,6 +252,8 @@ struct Polar {
/// @return The rotated vector
static Polar Rotate(const Polar& v, Angle a);
};
*/
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;

View File

@ -46,12 +46,11 @@ SphericalOf<T>::SphericalOf(float distance,
// this->vertical = vertical;
// }
template <>
SphericalOf<float> SphericalOf<float>::FromPolar(Polar polar) {
AngleOf<float> horizontal = polar.angle;
AngleOf<float> vertical = AngleOf<float>(0);
SphericalOf<float> r =
SphericalOf<float>(polar.distance, horizontal, vertical);
template <typename T>
SphericalOf<T> SphericalOf<T>::FromPolar(PolarOf<T> polar) {
AngleOf<T> horizontal = polar.angle;
AngleOf<T> vertical = AngleOf<T>(0);
SphericalOf<T> r = SphericalOf(polar.distance, horizontal, vertical);
return r;
}
@ -208,18 +207,18 @@ template class SphericalOf<float>;
template class SphericalOf<signed short>;
//---------------------------------------
/*
Spherical::Spherical() {
this->distance = 0.0f;
this->horizontalAngle = 0.0f;
this->verticalAngle = 0.0f;
}
Spherical::Spherical(Polar polar) {
this->distance = polar.distance;
this->horizontalAngle = polar.angle;
this->verticalAngle = 0.0f;
}
// Spherical::Spherical(Polar polar) {
// this->distance = polar.distance;
// this->horizontalAngle = polar.angle;
// this->verticalAngle = 0.0f;
// }
Spherical::Spherical(float distance,
Angle horizontalAngle,
@ -299,52 +298,53 @@ Spherical Spherical::operator+(const Spherical& s2) const {
Vector3 v = v1 + v2;
Spherical r = Spherical(v);
return r;
/*
// This is the hard way...
if (v2.distance <= 0)
return Spherical(this->distance, this->horizontalAngle,
this->verticalAngle);
if (this->distance <= 0)
return v2;
// if (v2.distance <= 0)
// return Spherical(this->distance, this->horizontalAngle,
// this->verticalAngle);
// if (this->distance <= 0)
// return v2;
float deltaHorizontalAngle =
(float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle);
float horizontalRotation = deltaHorizontalAngle < 0
? 180 + deltaHorizontalAngle
: 180 - deltaHorizontalAngle;
float deltaVerticalAngle =
Angle::Normalize(v2.verticalAngle - this->verticalAngle);
float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle
: 180 - deltaVerticalAngle;
// float deltaHorizontalAngle =
// (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle);
// float horizontalRotation = deltaHorizontalAngle < 0
// ? 180 + deltaHorizontalAngle
// : 180 - deltaHorizontalAngle;
// float deltaVerticalAngle =
// Angle::Normalize(v2.verticalAngle - this->verticalAngle);
// float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle
// : 180 - deltaVerticalAngle;
if (horizontalRotation == 180 && verticalRotation == 180)
// angle is too small, take this angle and add the distances
return Spherical(this->distance + v2.distance, this->horizontalAngle,
this->verticalAngle);
// if (horizontalRotation == 180 && verticalRotation == 180)
// // angle is too small, take this angle and add the distances
// return Spherical(this->distance + v2.distance, this->horizontalAngle,
// this->verticalAngle);
Angle rotation = AngleBetween(*this, v2);
float newDistance =
Angle::CosineRuleSide(v2.distance, this->distance, rotation);
float angle =
Angle::CosineRuleAngle(newDistance, this->distance, v2.distance);
// Angle rotation = AngleBetween(*this, v2);
// float newDistance =
// Angle::CosineRuleSide(v2.distance, this->distance, rotation);
// float angle =
// Angle::CosineRuleAngle(newDistance, this->distance, v2.distance);
// Now we have to project the angle to the horizontal and vertical planes...
// The axis for the angle is the cross product of the two spherical vectors
// (which function we do not have either...)
float horizontalAngle = 0;
float verticalAngle = 0;
// // Now we have to project the angle to the horizontal and vertical
planes...
// // The axis for the angle is the cross product of the two spherical vectors
// // (which function we do not have either...)
// float horizontalAngle = 0;
// float verticalAngle = 0;
float newHorizontalAngle =
deltaHorizontalAngle < 0
? Angle::Normalize(this->horizontalAngle - horizontalAngle)
: Angle::Normalize(this->horizontalAngle + horizontalAngle);
float newVerticalAngle =
deltaVerticalAngle < 0
? Angle::Normalize(this->verticalAngle - verticalAngle)
: Angle::Normalize(this->verticalAngle + verticalAngle);
// float newHorizontalAngle =
// deltaHorizontalAngle < 0
// ? Angle::Normalize(this->horizontalAngle - horizontalAngle)
// : Angle::Normalize(this->horizontalAngle + horizontalAngle);
// float newVerticalAngle =
// deltaVerticalAngle < 0
// ? Angle::Normalize(this->verticalAngle - verticalAngle)
// : Angle::Normalize(this->verticalAngle + verticalAngle);
// Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle);
Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle);
*/
}
Spherical Spherical::operator+=(const Spherical& v) {
*this = *this + v;
@ -428,4 +428,5 @@ Spherical Spherical::RotateVertical(const Spherical& v, Angle a) {
Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat(),
v.verticalAngle.ToFloat() + a.ToFloat());
return r;
}
}
*/

View File

@ -6,12 +6,14 @@
#define SPHERICAL_H
#include "Angle.h"
#include "Polar.h"
// #include "Polar.h"
namespace Passer {
namespace LinearAlgebra {
struct Vector3;
template <typename T>
class PolarOf;
template <typename T>
class SphericalOf {
@ -29,7 +31,7 @@ class SphericalOf {
SphericalOf<T>();
SphericalOf<T>(float distance, AngleOf<T> horizontal, AngleOf<T> vertical);
static SphericalOf<T> FromPolar(Polar v);
static SphericalOf<T> FromPolar(PolarOf<T> v);
static SphericalOf<T> FromVector3(Vector3 v);
Vector3 ToVector3() const;
@ -96,7 +98,8 @@ class SphericalOf {
using SphericalSingle = SphericalOf<float>;
using Spherical16 = SphericalOf<signed short>;
using Spherical = SphericalSingle;
/*
/// @brief A spherical vector
/// @details This is a vector in 3D space using a spherical coordinate system.
/// It consists of a distance and the polar and elevation angles from a
@ -125,7 +128,7 @@ struct Spherical {
Spherical(float distance, Angle horizontalAngle, Angle verticalAngle);
/// @brief Convert polar coordinates to spherical coordinates
/// @param polar The polar coordinate
Spherical(Polar polar);
// Spherical(Polar polar);
/// @brief Convert 3D carthesian coordinates to spherical coordinates
/// @param v Vector in 3D carthesian coordinates;
Spherical(Vector3 v);
@ -228,11 +231,13 @@ struct Spherical {
static Spherical RotateHorizontal(const Spherical& v, Angle angle);
static Spherical RotateVertical(const Spherical& v, Angle angle);
};
*/
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#include "Polar.h"
#include "Vector3.h"
#endif

View File

@ -30,7 +30,9 @@ namespace Passer {
namespace LinearAlgebra {
struct Vector3;
struct Polar;
template <typename T>
class PolarOf;
// using Polar = PolarOf<float>
/// @brief A 2=dimensional vector
/// @remark This uses the right=handed carthesian coordinate system.
@ -51,7 +53,7 @@ struct Vector2 : Vec2 {
Vector2(Vector3 v);
/// @brief Convert a Polar vector to a 2-dimensional vector
/// @param v The vector in polar coordinates
Vector2(Polar v);
Vector2(PolarOf<float> v);
/// @brief Vector2 destructor
~Vector2();

View File

@ -32,9 +32,8 @@ Vector3::Vector3(Vector2 v) {
Vector3::Vector3(Spherical s) {
float verticalRad =
(90.0f - s.verticalAngle.ToFloat()) * Passer::LinearAlgebra::Deg2Rad;
float horizontalRad =
s.horizontalAngle.ToFloat() * Passer::LinearAlgebra::Deg2Rad;
(90.0f - s.vertical.ToFloat()) * Passer::LinearAlgebra::Deg2Rad;
float horizontalRad = s.horizontal.ToFloat() * Passer::LinearAlgebra::Deg2Rad;
float cosVertical = cosf(verticalRad);
float sinVertical = sinf(verticalRad);
float cosHorizontal = cosf(horizontalRad);

View File

@ -10,7 +10,9 @@
namespace Passer {
namespace LinearAlgebra {
struct Spherical;
// struct Spherical;
template <typename T>
class SphericalOf;
extern "C" {
/// <summary>
@ -56,7 +58,7 @@ struct Vector3 : Vec3 {
/// @brief Convert vector in spherical coordinates to 3d carthesian
/// coordinates
/// @param v The vector to convert
Vector3(Spherical v);
Vector3(SphericalOf<float> v);
/// @brief Vector3 destructor
~Vector3();

View File

@ -4,24 +4,25 @@
#include <limits>
#include "Polar.h"
#include "Spherical.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Polar, FromVector2) {
Vector2 v = Vector2(0, 1);
Polar p = Polar(v);
Polar p = Polar::FromVector2(v);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "s.angle 0 0 1";
v = Vector2(1, 0);
p = Polar(v);
p = Polar::FromVector2(v);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 90.0F) << "s.angle 1 0";
v = Vector2(-1, 1);
p = Polar(v);
p = Polar::FromVector2(v);
EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1";
EXPECT_NEAR(p.angle.ToFloat(), -45.0F, 1.0e-05) << "s.angle -1 1";
@ -32,38 +33,38 @@ TEST(Polar, FromSpherical) {
Polar p;
s = Spherical(1, 0, 0);
p = Polar(s);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(1 0 0)";
s = Spherical(1, 45, 0);
p = Polar(s);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 45.0F) << "p.angle FromSpherical(1 45 0)";
s = Spherical(1, -45, 0);
p = Polar(s);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), -45.0F)
<< "p.angle FromSpherical(1 -45 0)";
s = Spherical(0, 0, 0);
p = Polar(s);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 0)";
s = Spherical(-1, 0, 0);
p = Polar(s);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 180.0F) << "p.angle FromSpherical(-1 0 0)";
s = Spherical(0, 0, 90);
p = Polar(s);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 90)";

View File

@ -4,6 +4,7 @@
#include <limits>
#include "Spherical.h"
#include "Vector3.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()

View File

@ -9,73 +9,72 @@
TEST(Spherical, FromVector3) {
Vector3 v = Vector3(0, 0, 1);
Spherical s = Spherical(v);
Spherical s = Spherical::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 0 1";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 0 0 1";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 0 1";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 0 0 1";
v = Vector3(0, 1, 0);
s = Spherical(v);
s = Spherical::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor 0 1 0";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 90.0F) << "s.vert 0 1 0";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 1 0";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 90.0F) << "s.vert 0 1 0";
v = Vector3(1, 0, 0);
s = Spherical(v);
s = Spherical::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 90.0F) << "s.hor 1 0 0";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert 1 0 0";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 90.0F) << "s.hor 1 0 0";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 1 0 0";
}
TEST(Spherical, FromPolar) {
Polar p = Polar(1, 0);
Spherical s = Spherical(p);
Spherical s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(1 0)";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 0)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(1 0)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 0)";
p = Polar(1, 45);
s = Spherical(p);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 45.0F) << "s.hor Polar(1 45)";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 45)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 45.0F) << "s.hor Polar(1 45)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 45)";
p = Polar(1, -45);
s = Spherical(p);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), -45.0F) << "s.hor Polar(1 -45)";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(1 -45)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -45.0F) << "s.hor Polar(1 -45)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 -45)";
p = Polar(0, 0);
s = Spherical(p);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 0.0F) << "s.hor Polar(0 0)";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(0 0)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(0 0)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(0 0)";
p = Polar(-1, 0);
s = Spherical(p);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)";
EXPECT_FLOAT_EQ(s.horizontalAngle.ToFloat(), 180.0F) << "s.hor Polar(-1 0)";
EXPECT_FLOAT_EQ(s.verticalAngle.ToFloat(), 0.0F) << "s.vert Polar(-1 0)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 180.0F) << "s.hor Polar(-1 0)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(-1 0)";
}
TEST(Spherical, Incident1) {
Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f);
Spherical s = Spherical(v);
Spherical s = Spherical::FromVector3(v);
Spherical sr = Spherical(2.49F, 98.18f, 24.4F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-01);
EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(),
1.0e-02);
EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-02);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-02);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-02);
Vector3 r = Vector3(sr);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0";
@ -85,13 +84,12 @@ TEST(Spherical, Incident1) {
TEST(Spherical, Incident2) {
Vector3 v = Vector3(1.0f, 0.0f, 1.0f);
Spherical s = Spherical(v);
Spherical s = Spherical::FromVector3(v);
Spherical sr = Spherical(1.4142135623F, 45.0f, 0.0F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-05);
EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(),
1.0e-05);
EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05);
Vector3 r = Vector3(sr);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
@ -99,13 +97,12 @@ TEST(Spherical, Incident2) {
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06);
v = Vector3(0.0f, 1.0f, 1.0f);
s = Spherical(v);
s = Spherical::FromVector3(v);
sr = Spherical(1.4142135623F, 0.0f, 45.0F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-05);
EXPECT_NEAR(s.horizontalAngle.ToFloat(), sr.horizontalAngle.ToFloat(),
1.0e-05);
EXPECT_NEAR(s.verticalAngle.ToFloat(), sr.verticalAngle.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05);
r = Vector3(sr);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
@ -113,12 +110,12 @@ TEST(Spherical, Incident2) {
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06);
v = Vector3(1.0f, 1.0f, 1.0f);
s = Spherical(v);
s = Spherical::FromVector3(v);
r = Vector3(s);
EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02);
EXPECT_NEAR(s.horizontalAngle.ToFloat(), 45.0F, 1.0e-02);
EXPECT_NEAR(s.verticalAngle.ToFloat(), 35.26F, 1.0e-02);
EXPECT_NEAR(s.horizontal.ToFloat(), 45.0F, 1.0e-02);
EXPECT_NEAR(s.vertical.ToFloat(), 35.26F, 1.0e-02);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06);
@ -146,14 +143,14 @@ TEST(Spherical, Addition) {
v2 = Spherical(1, -45, 0);
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 0) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 0) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 0) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 0) << "Addition(1 -45 0)";
v2 = Spherical(1, 0, 90);
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.horizontalAngle.ToFloat(), 45) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.verticalAngle.ToFloat(), 45) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 45) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 45) << "Addition(1 0 90)";
}
#endif

View File

@ -1,7 +1,7 @@
#if GTEST
#include <gtest/gtest.h>
#include <limits>
#include <math.h>
#include <limits>
#include "Vector2.h"
@ -13,21 +13,21 @@ TEST(Vector2, FromPolar) {
Vector2 r;
v = Vector2(0, 1);
p = Polar(v);
p = Polar::FromVector2(v);
r = Vector2(p);
EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 1)";
EXPECT_FLOAT_EQ(r.y, 1.0F) << "FromPolar(0 1)";
v = Vector2(1, 0);
p = Polar(v);
p = Polar::FromVector2(v);
r = Vector2(p);
EXPECT_FLOAT_EQ(r.x, 1.0F) << "FromPolar(1 0)";
EXPECT_NEAR(r.y, 0.0F, 1.0e-07) << "FromPolar(1 0)";
v = Vector2(0, 0);
p = Polar(v);
p = Polar::FromVector2(v);
r = Vector2(p);
EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 0)";

View File

@ -9,7 +9,7 @@
TEST(Vector3, FromSpherical) {
Vector3 v = Vector3(0, 0, 1);
Spherical s = Spherical(v);
Spherical s = Spherical::FromVector3(v);
Vector3 r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 0 1";
@ -17,7 +17,7 @@ TEST(Vector3, FromSpherical) {
EXPECT_FLOAT_EQ(r.Forward(), 1.0F) << "toVector3.z 0 0 1";
v = Vector3(0, 1, 0);
s = Spherical(v);
s = Spherical::FromVector3(v);
r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 1 0";
@ -25,7 +25,7 @@ TEST(Vector3, FromSpherical) {
EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 0 1 0";
v = Vector3(1, 0, 0);
s = Spherical(v);
s = Spherical::FromVector3(v);
r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 1.0F) << "toVector3.x 1 0 0";