简单实用的反三角函数库
周继光
2006-2-27
小弟对编程刚入门不久,自学路也是看着各位前辈们的贴子
走过来的,现偶有小得,不敢独享,遂与大家分享。
小弟在写一个OpenGL引擎时,需要用到反余函数,但找了
好久都没找到,C语言的数学库提供的反三角函数又不好用,所
以便自己实现了一个,采用的是间单的查表法。
恳请各位前辈指点不足,新手朋友们提问,欢迎大家灌水!
FMath.h 文件定义如下:
//2006-1-20
//1.0
//周继光
#ifndef FMATH_H_
#define FMATH_H_
const float PI = 3.1415926535897932384626433832795f;
const float PI2 = 6.283185307179586476925286766559f;
const float A_PI = 0.017453292519943295769236907684886f;
const float PI_A = 57.324840764331210191082802547771f;
//
//常用算法定义
///
template
T Max( T a, T b )
{
return ( a > b ? a : b );
}
template
T Min( T a, T b )
{
return ( a > b ? b : a );
}
template
void ReleasePointer( T &point )
{
if( NULL != point )
{
delete[] point;
}
point = NULL;
}
template
void CopyObject( T &Destination, T &Source )
{
memcpy( &Destination, &Source, sizeof( Destination ) );
}
typedef union
{
int i;
float f;
}INTORFLOAT;
class CFloat
{
public:
float Absolute( float f )
{
INTORFLOAT temp;
temp.f = f;
temp.i &= 0x7fffffff;
return temp.f;
}
int ChangeToInt( float f )
{
INTORFLOAT basic, temp;
basic.f = 12582912.0f;
temp.f = f;
temp.f += basic.f;
temp.i -= basic.i;
return temp.i;
}
bool AsZero( float f )
{
return Absolute( f ) < 0.000001;
}
bool BiggerThanZero( float f )
{
INTORFLOAT temp;
temp.f = f;
temp.i &= 0x80000000;
return !temp.i;
}
bool SmallThanZero( float f )
{
INTORFLOAT temp;
temp.f = f;
temp.i &= 0x80000000;
return !( !temp.i );
}
/*
float UINT64ToFloat( UINT64 uint64 )
{
TSC tsc;
tsc.tsc = uint64;
float ret = ( float )tsc.low + ( float )tsc.heigh * 4294967296.0f;
return ret;
}
*/
};
//
//end
///
//Singleton template define
///
template
{
static T* ms_Singleton;
public:
Singleton( void )
{
assert( !ms_Singleton );
int offset = (int)(T*)1 - (int)(Singleton
ms_Singleton = (T*)((int)this + offset);
}
~Singleton( void )
{ assert( ms_Singleton );
ms_Singleton = 0;
}
static T& GetSingleton( void )
{
assert( ms_Singleton );
return ( *ms_Singleton );
}
static T* GetSingletonPtr( void )
{
assert( ms_Singleton );
return ( ms_Singleton );
}
};
template
/
//end
/
//精度控制 注意:精度定义不要大于7。
const DWORD MATH_PRECISION = 6;
const DWORD MATH_CONSTANT = 128 << MATH_PRECISION;
const DWORD MATH_MAX = MATH_CONSTANT - 1;
const DWORD MATH_LOCA = MATH_CONSTANT >> 2;
const float MATH_API = MATH_CONSTANT / PI2;
const float MATH_PIA = 1.0f / MATH_API;
const float MATH_RATE = 360.0f / MATH_CONSTANT;
class CMath : public Singleton
{
protected:
float m_sintable[MATH_CONSTANT];
public:
CMath::CMath()
{
for( DWORD dwLoop = 0; dwLoop < MATH_CONSTANT; ++dwLoop )
{
m_sintable[dwLoop] = ( float )sin( ( double )dwLoop * MATH_PIA );
}
}
~CMath(){}
float Sin( float theta );
float Cos( float theta );
float ArcSin( float sin );
float ArcCos( float cos );
};
#define MATH_INSTANCE static CMath math;
#define MATH CMath::GetSingleton()
inline float CMath::Sin( float theta )
{
theta = theta * MATH_API;
CFloat Float;
return m_sintable[( Float.ChangeToInt( theta ) )
& MATH_MAX];
}
inline float CMath::Cos( float theta )
{
theta = theta * MATH_API;
CFloat Float;
return m_sintable[( Float.ChangeToInt( theta ) + MATH_LOCA )
& MATH_MAX];
}
///*
//二分查找法
inline float CMath::ArcSin( float sina )
{
CFloat Float;
sina = Float.Absolute( sina );
if( sina > 1.0f )
{
return 0.0f;
}
if( sina >= m_sintable[MATH_LOCA - 1] )
{
return 90.0f;
}
float sintemp = 1.0f / sina;
DWORD dwBegin = 0;
DWORD dwEnd = MATH_LOCA;
DWORD dwMid = 0;
DWORD dwNumber = 0;
while( 1 != dwNumber )
{
dwNumber = ( dwEnd - dwBegin ) >> 1;
dwMid = dwNumber + dwBegin;
if( sina < m_sintable[dwMid] )
{
if( sina >= m_sintable[dwMid-1] )
{
return( float )( dwMid - 1 ) * m_sintable[dwMid-1] * sintemp * MATH_RATE;
}
else
{
dwEnd = dwMid;
}
}
else
{
dwBegin = dwMid;
}
}
return 90.0f;
}
//*/
/*
//顺序搜索法
inline float CMath::ArcSin( float sina )
{
CFloat Float;
sina = Float.Absolute( sina );
if( sina > 1.0f )
{
return 0.0f;
}
if( sina >= m_sintable[MATH_LOCA - 1] )
{
return 90.0f;
}
if( sina < m_sintable[1] )
{
return 0.0f;
}
float sintemp = 1.0f / sina;
for( DWORD dwLoop = 1; dwLoop < MATH_LOCA; ++dwLoop )
{
if( sina < m_sintable[dwLoop] )
{
return ( float )( dwLoop - 1 ) * m_sintable[dwLoop-1] * sintemp * MATH_RATE;
}
}
return 90.0f;
}
*/
inline float CMath::ArcCos( float cos )
{
return ( 90.0f - ArcSin( cos ) );
}
#endif
如此使用:
TEST.CPP :
#include
#include
#include
#include
#include
#include"FMath.h"
MATH_INSTANCE
int main()
{
for( DWORD dwLoop = 0; dwLoop <= 90; ++dwLoop )
{
cout<<"Angle in: "<
cout<
{
cout<<"Angle in: "<
return 0;
}