|
Boost : |
From: Michael Stevens (michael_at_[hidden])
Date: 2001-07-10 19:39:20
Is there any interest in adding an angular arithmatic class template for
inclusion in Boost?
RATIONAL
When working with numerical algorithms, arithmetic with angles is always
a nasty issue. Normalising is essential. The class angle provides an
efficient EXPLICIT normalisation of angles in the -Pi..Pi (inclusive)
range.
Angles are represented as a class so that their normalisation status is
hidden. However they can be readily converted in a normalised form back
to their basic type. This allows the normal arithmetic operations to be
used. Where angles need to be compared or their difference found an
explicit normalisation between to angles is provided
Usage is simple: to normalise a double
angled(55.5);
to normalise an angle so the difference from the second angle is within
Pi..Pi
angled(55.5).from(52.1);
It also includes constants for Pi, Pi2 (two pi) and Deg2Rad (pi/180),
e.g.
double rad = 10. * angled::Deg2Rad;
Why include in BOOST?
a) Normalised angular arithmetic needs an efficient portable
solution
b) It fits (can fit!) well with other boost libraries such as
Quaternions and the general emphasis on mathematical algorithms
c) C++ needs a Pi constant!
Why NOT include in BOOST?
1. A general Modulo arthemtic class may be more useful
2. The structure and nameing of mathematical libraries in Boost
is at present very fluid.
So people can see what is envolved I appended a simplified (no
portablity ifdefs) of what I use.
/*
* (c) Michael Stevens, Australian Centre for Field Robotics 2000
*/
/*
* Angle arithmetic operations
* Manipulates angles using a normalised -PI>=angle<=PI representation
* The algorithm has proven to be the most numerically acurate.
* For implementations where the cost of fmod is low it is also the
most
* efficient in all cases.
* Class is templatised for a model of real for which fmod is defined
* For float a specialisation using fmodf is used in VC to improve
efficiency
*/
namespace angleArith
{
template <class real>
class angle
{
private:
real a; // Unnormalised angle
// Specialisation of fmod for float to fmodf
inline real myfmod(real x, real y)
{
return std::fmod(x,y);
}
#endif
public:
// The mathematical constants
static const real Pi, Pi2, Deg2Rad;
angle (const real& unNorm)
/* Initialise from an unnormailised angle */
{ a = unNorm;
}
operator real ()
/* Normalised in range +/- PI
* Side effect is to permenantly normalise a for faster access
subsequently */
{
a = myfmod(a, Pi2);
if (a > Pi) {
a -= Pi2;
}
else if (a < -Pi) {
a += Pi2;
}
return a;
}
real from (real a2) const
/* Normalise an angle so it is withing range +/- PI from a2 */
{
/* Normalised difference */
angle<real> a = this->a - a2;
/* Rebase to a2 */
return real(a) + a2;
}
};
template <class real>
const real angle<real>::Pi = real(3.1415926535898);
template <class real>
const real angle<real>::Pi2 = real(3.1415926535898 * 2.);
template <class real>
const real angle<real>::Deg2Rad = real(3.1415926535898) / real(180.);
// Predefined types ready to use for Double and Float
typedef angle<double> angled;
typedef angle<float> anglef;
}//namespace angleArith
Michael Stevens
Senior Research Engineer
Tel: +61 2 93512075 Fax: +61 2 93517474
Australian Centre for Field Robotics
Rose Street Building J04
The University of Sydney NSW, 2006
Australia
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk