b511995b2f
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3619 a95241bf-73f2-0310-859d-f6bbb57e9c96
418 lines
8.8 KiB
C++
418 lines
8.8 KiB
C++
//------------------------------------------------------------------------------
|
|
// Copyright (c) 2001-2002, OpenBeOS
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
// to deal in the Software without restriction, including without limitation
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
// DEALINGS IN THE SOFTWARE.
|
|
//
|
|
// File Name: Angle.cpp
|
|
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
|
// Description: Angle class for speeding up trig functions
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
#include "Angle.h"
|
|
#include <math.h>
|
|
|
|
#ifndef ANGLE_PI
|
|
#define ANGLE_PI 3.14159265358979323846
|
|
#endif
|
|
|
|
bool tables_initialized=false;
|
|
float sintable[360], costable[360], tantable[360];
|
|
|
|
/*!
|
|
\brief Constructor
|
|
\param angle Value in degrees
|
|
*/
|
|
Angle::Angle(float angle)
|
|
{
|
|
angle_value=angle;
|
|
if(tables_initialized==false)
|
|
{
|
|
InitTrigTables();
|
|
tables_initialized=true;
|
|
}
|
|
}
|
|
|
|
//! Constructor
|
|
Angle::Angle(void)
|
|
{
|
|
angle_value=0;
|
|
if(tables_initialized==false)
|
|
{
|
|
InitTrigTables();
|
|
tables_initialized=true;
|
|
}
|
|
}
|
|
|
|
//! Empty destructor
|
|
Angle::~Angle(void)
|
|
{
|
|
}
|
|
|
|
//! Constrains angle to 0 <= angle <= 360
|
|
void Angle::Normalize(void)
|
|
{
|
|
// if the value of the angle is >=360 or <0, make it so that it is
|
|
// within those bounds
|
|
|
|
if(angle_value>359)
|
|
{
|
|
while(angle_value>359)
|
|
angle_value-=360;
|
|
return;
|
|
}
|
|
if(angle_value<0)
|
|
{
|
|
while(angle_value<0)
|
|
angle_value+=360;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Obtains the sine of the angle
|
|
\return The sine of the angle
|
|
*/
|
|
float Angle::Sine(void)
|
|
{
|
|
return sintable[(int)angle_value];
|
|
}
|
|
|
|
/*!
|
|
\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)
|
|
{
|
|
// Returns the inverse sine of a value in the range 0 <= value <= 1 via
|
|
// reverse-lookup any value out of range causes the function to return 0
|
|
uint16 i=90;
|
|
|
|
// Filter out bad values
|
|
if(value<0)
|
|
value*=-1;
|
|
|
|
if(value > 1)
|
|
return Angle(0);
|
|
|
|
while(value < sintable[i])
|
|
i--;
|
|
|
|
// current sintable[i] is less than value. Pick the degree value which is closer
|
|
// to the passed value
|
|
if( (value - sintable[i]) > (sintable[i+1] - value) )
|
|
return (i+1);
|
|
|
|
return Angle(i); // value is closer to previous
|
|
}
|
|
|
|
|
|
/*!
|
|
\brief Obtains the cosine of the angle
|
|
\return The cosine of the angle
|
|
*/
|
|
float Angle::Cosine(void)
|
|
{
|
|
return costable[(int)angle_value];
|
|
}
|
|
|
|
/*!
|
|
\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)
|
|
{
|
|
// Returns the inverse cosine of a value in the range 0 <= value <= 1 via
|
|
// reverse-lookup any value out of range causes the function to return 0
|
|
uint16 i=90;
|
|
|
|
// Filter out bad values
|
|
if(value<0)
|
|
value*=-1;
|
|
|
|
if(value > 1)
|
|
return 0;
|
|
|
|
while(value > costable[i])
|
|
i--;
|
|
|
|
// current costable[i] is less than value. Pick the degree value which is closer
|
|
// to the passed value
|
|
if( (value - costable[i]) < (costable[i+1] - value) )
|
|
return (i+1);
|
|
|
|
return Angle(i); // value is closer to previous
|
|
}
|
|
|
|
/*!
|
|
\brief Obtains the tangent of the angle
|
|
\return The tangent of the angle
|
|
*/
|
|
float Angle::Tangent(int *status)
|
|
{
|
|
if(angle_value==90 || angle_value==270)
|
|
{
|
|
if(status)
|
|
*status=0;
|
|
return 0.0;
|
|
}
|
|
|
|
return tantable[(int)angle_value];
|
|
}
|
|
|
|
/*!
|
|
\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)
|
|
{
|
|
uint16 i=90;
|
|
|
|
// Filter out bad values
|
|
if(value<0)
|
|
value*=-1;
|
|
|
|
if(value > 1)
|
|
return Angle(0);
|
|
|
|
while(value > tantable[i])
|
|
i--;
|
|
|
|
if( (value - tantable[i]) < (tantable[i+1] - value) )
|
|
return (i+1);
|
|
|
|
return Angle(i); // value is closer to previous
|
|
}
|
|
|
|
/*!
|
|
\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(void)
|
|
{
|
|
// We can get away with not doing extra value checks because of the order in
|
|
// which the checks are done.
|
|
if(angle_value < 90)
|
|
return 1;
|
|
|
|
if(angle_value < 180)
|
|
return 2;
|
|
|
|
if(angle_value < 270)
|
|
return 3;
|
|
|
|
return 4;
|
|
}
|
|
|
|
/*!
|
|
\brief Obtains the angle constrained to between 0 and 180 inclusive
|
|
\return The constrained value
|
|
*/
|
|
Angle Angle::Constrain180(void)
|
|
{
|
|
// Constrains angle to 0 <= angle < 180
|
|
float val=angle_value;
|
|
|
|
if(angle_value<180)
|
|
return Angle(angle_value);
|
|
|
|
while(!(val<180))
|
|
val-=90;
|
|
return Angle(val);
|
|
}
|
|
|
|
/*!
|
|
\brief Obtains the angle constrained to between 0 and 90 inclusive
|
|
\return The constrained value
|
|
*/
|
|
Angle Angle::Constrain90(void)
|
|
{
|
|
// Constrains angle to 0 <= angle < 90
|
|
float val=angle_value;
|
|
|
|
if(angle_value<90)
|
|
return Angle(angle_value);
|
|
|
|
while(!(val<90))
|
|
val-=90;
|
|
return Angle(val);
|
|
}
|
|
|
|
/*!
|
|
\brief Sets the angle's value and normalizes the value
|
|
\param angle Value in degrees
|
|
*/
|
|
void Angle::SetValue(float angle)
|
|
{
|
|
angle_value=angle;
|
|
Normalize();
|
|
}
|
|
|
|
/*!
|
|
\brief Returns the value of the angle
|
|
\return The angle's value in degrees
|
|
*/
|
|
float Angle::Value(void) const
|
|
{
|
|
return angle_value;
|
|
}
|
|
|
|
//! Initializes the global trig tables
|
|
void Angle::InitTrigTables(void)
|
|
{
|
|
int8 i;
|
|
double sval,cval,tval,current_radian;
|
|
|
|
for(i=0;i<90; i++)
|
|
{
|
|
current_radian=(i * ANGLE_PI)/180.0;
|
|
|
|
// Get these so that we can do some superfast assignments
|
|
sval=(float)sin(current_radian);
|
|
cval=(float)cos(current_radian);
|
|
|
|
// Do 4 assignments, taking advantage of sin/cos symmetry
|
|
sintable[i]=sval;
|
|
sintable[i+90]=cval;
|
|
sintable[i+180]=sval * -1;
|
|
sintable[i+270]=cval * -1;
|
|
|
|
costable[i]=cval;
|
|
costable[i+90]=sval * -1;
|
|
costable[i+180]=cval * -1;
|
|
costable[i+270]=sval;
|
|
|
|
tval=sval/cval;
|
|
|
|
tantable[i]=tval;
|
|
tantable[i+90]=tval;
|
|
tantable[i+180]=tval;
|
|
tantable[i+270]=tval;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded assignment operator
|
|
\param from Angle to copy the value from
|
|
\return The angle's new value
|
|
*/
|
|
Angle & Angle::operator=(const Angle &from)
|
|
{
|
|
angle_value=from.angle_value;
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded assignment operator
|
|
\param from New value of the angle
|
|
\return The angle's new value
|
|
*/
|
|
Angle & Angle::operator=(const float &from)
|
|
{
|
|
angle_value=from;
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded assignment operator
|
|
\param from New value of the angle
|
|
\return The angle's new value
|
|
*/
|
|
Angle & Angle::operator=(const long &from)
|
|
{
|
|
angle_value=(float)from;
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded assignment operator
|
|
\param from New value of the angle
|
|
\return The angle's new value
|
|
*/
|
|
Angle & Angle::operator=(const int &from)
|
|
{
|
|
angle_value=(float)from;
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded equivalence operator
|
|
\param The angle to compare to
|
|
\return True if equal, false if not
|
|
*/
|
|
bool Angle::operator==(const Angle &from)
|
|
{
|
|
return (angle_value==from.angle_value)?true:false;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded inequality operator
|
|
\param The angle to compare to
|
|
\return True if not equal, false if not
|
|
*/
|
|
bool Angle::operator!=(const Angle &from)
|
|
{
|
|
return (angle_value!=from.angle_value)?true:false;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded greater than operator
|
|
\param The angle to compare to
|
|
\return True if greater, false if not
|
|
*/
|
|
bool Angle::operator>(const Angle &from)
|
|
{
|
|
return (angle_value>from.angle_value)?true:false;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded less than operator
|
|
\param The angle to compare to
|
|
\return True if less than, false if not
|
|
*/
|
|
bool Angle::operator<(const Angle &from)
|
|
{
|
|
return (angle_value<from.angle_value)?true:false;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded greater than or equal to operator
|
|
\param The angle to compare to
|
|
\return True if greater than or equal to, false if not
|
|
*/
|
|
bool Angle::operator>=(const Angle &from)
|
|
{
|
|
return (angle_value>=from.angle_value)?true:false;
|
|
}
|
|
|
|
/*!
|
|
\brief Overloaded less than or equal to operator
|
|
\param The angle to compare to
|
|
\return True if less than or equal to, false if not
|
|
*/
|
|
bool Angle::operator<=(const Angle &from)
|
|
{
|
|
return (angle_value<=from.angle_value)?true:false;
|
|
}
|