#include "Spherical.h" #include "Angle.h" #include "Quaternion.h" #include Spherical::Spherical() { this->distance = 0.0f; this->horizontalAngle = 0.0f; this->verticalAngle = 0.0f; } Spherical::Spherical(Polar polar) { this->distance = polar.distance; this->horizontalAngle = polar.angle; this->verticalAngle = 0.0f; } Spherical::Spherical(float distance, Angle horizontalAngle, Angle verticalAngle) { if (distance < 0) { this->distance = -distance; this->horizontalAngle = Angle::Normalize(horizontalAngle - 180); this->verticalAngle = verticalAngle; } else { this->distance = distance; this->horizontalAngle = Angle::Normalize(horizontalAngle); this->verticalAngle = Angle::Normalize(verticalAngle); } } Spherical::Spherical(Vector3 v) { this->distance = v.magnitude(); if (distance == 0.0f) { this->verticalAngle = 0.0f; this->horizontalAngle = 0.0f; } else { this->verticalAngle = (90.0f - acosf(v.Up() / this->distance) * Angle::Rad2Deg); this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; } } const Spherical Spherical::zero = Spherical(0.0f, 0.0f, 0.0f); const Spherical Spherical::forward = Spherical(1.0f, 0.0f, 0.0f); const Spherical Spherical::back = Spherical(1.0f, 180.0f, 0.0f); const Spherical Spherical::right = Spherical(1.0f, 90.0f, 0.0f); const Spherical Spherical::left = Spherical(1.0f, -90.0f, 0.0f); const Spherical Spherical::up = Spherical(1.0f, 0.0f, 90.0f); const Spherical Spherical::down = Spherical(1.0f, 0.0f, -90.0f); bool Spherical::operator==(const Spherical &v) const { return (this->distance == v.distance && this->horizontalAngle == v.horizontalAngle && this->verticalAngle == v.verticalAngle); } Spherical Spherical::Normalize(const Spherical &v) { Spherical r = Spherical(1, v.horizontalAngle, v.verticalAngle); return r; } Spherical Spherical::normalized() const { Spherical r = Spherical(1, this->horizontalAngle, this->verticalAngle); return r; } Spherical Spherical::operator-() const { Spherical v = Spherical(this->distance, this->horizontalAngle + 180.0f, this->verticalAngle + 180.0f); return v; } Spherical Spherical::operator+(const Spherical &s2) const { // let's do it the easy way... Vector3 v1 = Vector3(*this); Vector3 v2 = Vector3(s2); Vector3 v = v1 + v2; Spherical r = Spherical(v); return r; /* // This is the hard way... if (v2.distance <= 0) return Spherical(this->distance, this->horizontalAngle, this->verticalAngle); if (this->distance <= 0) return v2; float deltaHorizontalAngle = (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle); float horizontalRotation = deltaHorizontalAngle < 0 ? 180 + deltaHorizontalAngle : 180 - deltaHorizontalAngle; float deltaVerticalAngle = Angle::Normalize(v2.verticalAngle - this->verticalAngle); float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle : 180 - deltaVerticalAngle; if (horizontalRotation == 180 && verticalRotation == 180) // angle is too small, take this angle and add the distances return Spherical(this->distance + v2.distance, this->horizontalAngle, this->verticalAngle); Angle rotation = AngleBetween(*this, v2); float newDistance = Angle::CosineRuleSide(v2.distance, this->distance, rotation); float angle = Angle::CosineRuleAngle(newDistance, this->distance, v2.distance); // Now we have to project the angle to the horizontal and vertical planes... // The axis for the angle is the cross product of the two spherical vectors // (which function we do not have either...) float horizontalAngle = 0; float verticalAngle = 0; float newHorizontalAngle = deltaHorizontalAngle < 0 ? Angle::Normalize(this->horizontalAngle - horizontalAngle) : Angle::Normalize(this->horizontalAngle + horizontalAngle); float newVerticalAngle = deltaVerticalAngle < 0 ? Angle::Normalize(this->verticalAngle - verticalAngle) : Angle::Normalize(this->verticalAngle + verticalAngle); Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle); */ } Spherical Spherical::operator+=(const Spherical &v) { *this = *this + v; return *this; } Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) { return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); } Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) { return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle); } Spherical Spherical::operator*=(float f) { this->distance *= f; return *this; } Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) { return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); } Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) { return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle); } Spherical Spherical::operator/=(float f) { this->distance /= f; return *this; } // float Spherical::GetSwing() { // // Not sure if this is correct // return sqrtf(horizontalAngle * horizontalAngle + // verticalAngle * verticalAngle); // } // float Spherical::Distance(const Spherical &s1, const Spherical &s2) { // float d = 0; // return d; // } #include "AngleUsing.h" #include "FloatSingle.h" #include "Vector3.h" const float epsilon = 1E-05f; const float Rad2Deg = 57.29578F; Angle Spherical::AngleBetween(const Spherical &v1, const Spherical &v2) { // float denominator = sqrtf(v1_3.sqrMagnitude() * v2_3.sqrMagnitude()); float denominator = v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance * // v2.distance * v2.distance); if (denominator < epsilon) return 0; Vector3 v1_3 = Vector3(v1); Vector3 v2_3 = Vector3(v2); float dot = Vector3::Dot(v1_3, v2_3); float fraction = dot / denominator; if (isnan(fraction)) return fraction; // short cut to returning NaN universally float cdot = Float::Clamp(fraction, -1.0, 1.0); float r = ((float)acos(cdot)) * Rad2Deg; return r; } Spherical Spherical::Rotate(const Spherical &v, Angle horizontalAngle, Angle verticalAngle) { Spherical r = Spherical(v.distance, v.horizontalAngle + horizontalAngle, v.verticalAngle + verticalAngle); return r; } Spherical Spherical::RotateHorizontal(const Spherical &v, Angle a) { Spherical r = Spherical(v.distance, v.horizontalAngle + a, v.verticalAngle); return r; } Spherical Spherical::RotateVertical(const Spherical &v, Angle a) { Spherical r = Spherical(v.distance, v.horizontalAngle, v.verticalAngle + a); return r; }