Created
January 26, 2014 14:51
-
-
Save Klaim/8633895 to your computer and use it in GitHub Desktop.
SphereVector work in progress - needs check
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef HGUARD_NETRUSH_ZONEVIEW_SPHERICAL_HPP__ | |
#define HGUARD_NETRUSH_ZONEVIEW_SPHERICAL_HPP__ | |
#include <iosfwd> | |
#include <OgreMath.h> | |
#include <OgreVector3.h> | |
#include <OgreQuaternion.h> | |
#include "api.hpp" | |
namespace netrush { | |
namespace zoneview { | |
/** Spherical coordinates vector, used for spherical coordinates and transformations. | |
Some example values: | |
( radius = 1.0, theta = 0.0deg , phi = 0.0deg ) <=> Y unit vector in cartesian space | |
( radius = 1.0, theta = 90.0deg, phi = 0.0deg ) <=> Z unit vector in cartesian space | |
( radius = 1.0, theta = 90.0deg , phi = 90.0deg ) <=> X unit vector in cartesian space | |
*/ | |
struct SphereVector | |
{ | |
Ogre::Real radius; ///< Rho or Radius is the distance from the center of the sphere. | |
Ogre::Radian theta; ///< Theta is the angle around the x axis (latitude angle counterclockwise), values range from 0 to PI. | |
Ogre::Radian phi; ///< Phi is the angle around the y axis (longitude angle counterclockwise), values range from 0 to 2PI. | |
NETRUSH_ZONEVIEW_API static const SphereVector ZERO; | |
NETRUSH_ZONEVIEW_API static const SphereVector UNIT_X; | |
NETRUSH_ZONEVIEW_API static const SphereVector UNIT_Y; | |
NETRUSH_ZONEVIEW_API static const SphereVector UNIT_Z; | |
NETRUSH_ZONEVIEW_API static const SphereVector NEGATIVE_UNIT_X; | |
NETRUSH_ZONEVIEW_API static const SphereVector NEGATIVE_UNIT_Y; | |
NETRUSH_ZONEVIEW_API static const SphereVector NEGATIVE_UNIT_Z; | |
SphereVector() = default; | |
SphereVector( Ogre::Real radius, Ogre::Radian theta, Ogre::Radian phi ) | |
: radius( std::move(radius) ), theta( std::move(theta) ), phi( std::move(phi) ) | |
{} | |
explicit SphereVector( const Ogre::Vector3& cartesian_vec ) | |
{ | |
*this = from_cartesian( cartesian_vec ); | |
} | |
void normalize() | |
{ | |
using namespace Ogre; | |
while( phi > Degree(360.f) ) phi -= Degree(360.f); | |
while( theta > Degree(180.f) ) theta -= Degree(180.f); | |
while( phi < Radian(0) ) phi += Degree(360.f); | |
while( theta < Radian(0) ) theta += Degree(180.f); | |
} | |
SphereVector normalized() const | |
{ | |
SphereVector svec{*this}; | |
svec.normalize(); | |
return svec; | |
} | |
/** @return a relative Cartesian vector coordinate from this relative spherical coordinate. */ | |
Ogre::Vector3 to_cartesian() const | |
{ | |
using namespace Ogre; | |
const auto svec = normalized(); | |
Vector3 result; | |
result.x = radius * Math::Sin( svec.phi ) * Math::Sin( svec.theta ); | |
result.z = radius * Math::Cos( svec.phi ) * Math::Sin( svec.theta ); | |
result.y = radius * Math::Cos( svec.theta ); | |
return result; | |
} | |
/** @return a relative spherical coordinate from a cartesian vector. */ | |
static SphereVector from_cartesian( const Ogre::Vector3& cartesian ) | |
{ | |
using namespace Ogre; | |
SphereVector result = SphereVector::ZERO; | |
result.radius = cartesian.length(); | |
if( result.radius == 0 ) | |
return result; | |
result.phi = Math::ATan2( cartesian.x, cartesian.z ); | |
result.theta = Math::ATan2( Math::Sqrt( Math::Sqr( cartesian.x ) + Math::Sqr( cartesian.z ) ), cartesian.y ); | |
result.normalize(); | |
return result; | |
} | |
friend SphereVector operator-( const SphereVector& value ) | |
{ | |
SphereVector result; | |
result.radius = -value.radius; | |
result.theta = -value.theta; | |
result.phi = -value.phi; | |
return result; | |
} | |
friend SphereVector operator+( const SphereVector& left, const SphereVector& right ) | |
{ | |
SphereVector result; | |
result.radius = left.radius + right.radius; | |
result.theta = left.theta + right.theta; | |
result.phi = left.phi + right.phi; | |
return result; | |
} | |
friend SphereVector operator-( const SphereVector& left, const SphereVector& right ) | |
{ | |
return left + (-right); | |
} | |
SphereVector& operator+=( const SphereVector& other ) | |
{ | |
*this = *this + other; | |
return *this; | |
} | |
SphereVector& operator-=( const SphereVector& other ) | |
{ | |
*this = *this - other; | |
return *this; | |
} | |
/// Rotation of the position around the relative center of the sphere. | |
friend SphereVector operator*( const SphereVector& sv, const Ogre::Quaternion& rotation ) | |
{ | |
const auto cartesian_vec = sv.to_cartesian(); | |
const auto rotated_vec = rotation * cartesian_vec; | |
SphereVector result { rotated_vec }; | |
result.normalize(); | |
return result; | |
} | |
/// Rotation of the position around the relative center of the sphere. | |
friend SphereVector operator*( const Ogre::Quaternion& rotation, const SphereVector& sv ) { return sv * rotation; } | |
/// Rotation of the position around the relative center of the sphere. | |
SphereVector& operator*=( const Ogre::Quaternion& rotation ) | |
{ | |
*this = *this * rotation; | |
return *this; | |
} | |
friend bool operator==( const SphereVector& left, const SphereVector& right ) | |
{ | |
return Ogre::Math::RealEqual( left.radius, right.radius ) | |
&& left.phi == right.phi | |
&& left.theta == right.theta | |
; | |
} | |
friend bool operator!=( const SphereVector& left, const SphereVector& right ) | |
{ | |
return !( left == right ); | |
} | |
}; | |
inline std::ostream& operator<<( std::ostream& out, const SphereVector& svec ) | |
{ | |
out << "{ radius = " << svec.radius | |
<< ", theta = " << svec.theta | |
<< ", phi = " << svec.phi | |
<< " }"; | |
return out; | |
} | |
inline bool real_equals( const SphereVector& left, const SphereVector& right, Ogre::Real tolerance = 1e-03 ) | |
{ | |
using namespace Ogre; | |
return Math::RealEqual( left.radius, right.radius, tolerance ) | |
&& Math::RealEqual( left.theta.valueAngleUnits(), right.theta.valueAngleUnits(), tolerance ) | |
&& Math::RealEqual( left.phi.valueAngleUnits(), right.phi.valueAngleUnits(), tolerance ) | |
; | |
} | |
}} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment