#include "Angle.h"
#include <math.h>
#ifndef ANGLE_PI
#define ANGLE_PI 3.14159265358979323846
#endif
static bool sTablesInitialized = false;
static float sSinTable[360];
static float sCosTable[360];
static float sTanTable[360];
\brief Constructor
\param angle Value in degrees
*/
Angle::Angle(float angle)
: fAngleValue(angle)
{
_InitTrigTables();
}
Angle::Angle()
: fAngleValue(0)
{
_InitTrigTables();
}
Angle::~Angle()
{
}
void
Angle::Normalize()
{
fAngleValue = fmodf(fAngleValue, 360);
if (fAngleValue < 0)
fAngleValue += 360;
}
\brief Obtains the sine of the angle
\return The sine of the angle
*/
float
Angle::Sine()
{
return sSinTable[(int)fAngleValue];
}
\brief Calculates an angle given a float value
\param value Number between 0 and 1 inclusive
\return The angle obtained or 0 if value passed was invalid
*/
Angle
Angle::InvSine(float value)
{
value = fabs(value);
if (value > 1)
return Angle(0);
uint16 i = 90;
while (value < sSinTable[i])
i--;
if ((value - sSinTable[i]) > (sSinTable[i + 1] - value))
return Angle(i + 1);
return Angle(i);
}
\brief Obtains the cosine of the angle
\return The cosine of the angle
*/
float
Angle::Cosine(void)
{
return sCosTable[(int)fAngleValue];
}
\brief Calculates an angle given a float value
\param value Number between 0 and 1 inclusive
\return The angle obtained or 0 if value passed was invalid
*/
Angle
Angle::InvCosine(float value)
{
value = fabs(value);
if (value > 1)
return 0;
uint16 i = 90;
while (value > sCosTable[i])
i--;
if ((value - sCosTable[i]) < (sCosTable[i + 1] - value))
return Angle(i + 1);
return Angle(i);
}
\brief Obtains the tangent of the angle
\return The tangent of the angle
*/
float
Angle::Tangent(int *status)
{
if (fAngleValue == 90 || fAngleValue == 270) {
if (status)
*status = 0;
return 0.0;
}
return sTanTable[(int)fAngleValue];
}
\brief Returns the inverse tangent of a value given
\param value Number between 0 and 1 inclusive
\return The angle found or 0 if value was invalid
*/
Angle
Angle::InvTangent(float value)
{
value = fabs(value);
if (value > 1)
return Angle(0);
uint16 i = 90;
while (value > sTanTable[i])
i--;
if ((value - sTanTable[i]) < (sTanTable[i+1] - value))
return Angle(i+1);
return Angle(i);
}
\brief Returns a value based on what quadrant the angle is in
\return
- \c 1: 0 <= angle <90
- \c 2: 90 <= angle < 180
- \c 3: 180 <= angle < 270
- \c 4: 270 <= angle < 360
*/
uint8
Angle::Quadrant()
{
if (fAngleValue < 90)
return 1;
if (fAngleValue < 180)
return 2;
if (fAngleValue < 270)
return 3;
return 4;
}
\brief Obtains the angle constrained to between 0 and 180 inclusive
\return The constrained value
*/
Angle
Angle::Constrain180()
{
if (fAngleValue < 180)
return Angle(fAngleValue);
float value = fmodf(fAngleValue, 180);;
if (value < 0)
value += 180;
return Angle(value);
}
\brief Obtains the angle constrained to between 0 and 90 inclusive
\return The constrained value
*/
Angle
Angle::Constrain90()
{
if (fAngleValue < 90)
return Angle(fAngleValue);
float value = fmodf(fAngleValue, 90);;
if (value < 0)
value += 90;
return Angle(value);
}
\brief Sets the angle's value and normalizes the value
\param angle Value in degrees
*/
void
Angle::SetValue(float angle)
{
fAngleValue = angle;
Normalize();
}
float
Angle::Value() const
{
return fAngleValue;
}
void
Angle::_InitTrigTables()
{
if (sTablesInitialized)
return;
sTablesInitialized = true;
for(int32 i = 0; i < 90; i++) {
double currentRadian = (i * ANGLE_PI) / 180.0;
double sinValue = sin(currentRadian);
double cosValue = cos(currentRadian);
sSinTable[i] = sinValue;
sSinTable[i + 90] = cosValue;
sSinTable[i + 180] = sinValue * -1;
sSinTable[i + 270] = cosValue * -1;
sCosTable[i] = cosValue;
sCosTable[i + 90] = sinValue * -1;
sCosTable[i + 180] = cosValue * -1;
sCosTable[i + 270] = sinValue;
double tanValue = sinValue / cosValue;
sTanTable[i] = tanValue;
sTanTable[i + 90] = tanValue;
sTanTable[i + 180] = tanValue;
sTanTable[i + 270] = tanValue;
}
}
Angle&
Angle::operator=(const Angle &from)
{
fAngleValue = from.fAngleValue;
return *this;
}
Angle&
Angle::operator=(const float &from)
{
fAngleValue = from;
return *this;
}
Angle&
Angle::operator=(const long &from)
{
fAngleValue = (float)from;
return *this;
}
Angle&
Angle::operator=(const int &from)
{
fAngleValue = (float)from;
return *this;
}
bool
Angle::operator==(const Angle &from)
{
return (fAngleValue == from.fAngleValue);
}
bool
Angle::operator!=(const Angle &from)
{
return (fAngleValue != from.fAngleValue);
}
bool
Angle::operator>(const Angle &from)
{
return (fAngleValue > from.fAngleValue);
}
bool
Angle::operator<(const Angle &from)
{
return (fAngleValue < from.fAngleValue);
}
bool
Angle::operator>=(const Angle &from)
{
return (fAngleValue >= from.fAngleValue);
}
bool
Angle::operator<=(const Angle &from)
{
return (fAngleValue <= from.fAngleValue);
}