Skip to content

Instantly share code, notes, and snippets.

# Const-me/SinCosAngle.cpp Last active Apr 7, 2018

 #define _USE_MATH_DEFINES #include struct Point { double x, y; }; // A class that contains a 2D angle as a pair of sine + cosine values. // Sometimes, this approach saves substantial CPU time that would be wasted running these trigonometry functions. // While reasonably efficient, one downside of this approach is it's hard to implement multiplication by a scalar value, i.e. linear interpolation. If that's your case, use quaternions instead, they work fine for 2D. class Angle { double x; // = cos(angle) double y; // = sin(angle) // Private constructor from raw values. Parameters must be normalized already. Angle( double _x, double _y ) : x( _x ), y( _y ) {} public: // Construct from radians Angle( double rad ) { x = cos( rad ); y = sin( rad ); } // Construct from a radius vector, by normalizing Angle( const Point &pt ) { double mul = 1.0 / sqrt( pt.x * pt.x + pt.y * pt.y ); x = pt.x * mul; y = pt.y * mul; } Angle( const Angle& that ) = default; Angle& operator=( const Angle& that ) = default; // Divide the angle by 2. The input angle is assumed to be between -Pi and +Pi. To inperpret the angle to be between 0 and 2*Pi, flip the result when y < 0 Angle half() const { // We do that by adding { 1, 0 } vector, and normalizing the result back onto the unit circle. This way it's a single square root, compared to 2 roots when using classical formulae. const double x2 = x + 1.0; const double len = sqrt( x2*x2 + y*y ); if( isnormal( len ) ) { const double mul = 1.0 / len; return Angle{ x2 * mul, y * mul }; } // The length of the result is a de-normalized float, i.e. very close to 0. This means the angle is very close to Pi. Therefore, the result is very close to pi/2 // All 3 exact zeros, -0.0, 0, and +0.0, are not normal numbers according to isnormal API, which is exactly what we want in this case. return Angle{ 0, ( y >= 0 ) ? 1.0 : -1.0 }; } // Flip the angle, it's the same as adding Pi to it. Angle operator-() const { return Angle{ -x, -y }; } // Multiply the angle by 2 Angle dbl() const { return Angle{ x*x - y*y, 2 * x*y }; } // Add angles Angle operator+( const Angle &that ) const { return Angle{ x*that.x - y*that.y, y*that.x + x*that.y }; } // Subtract angles Angle operator-( const Angle &that ) const { return Angle{ x*that.x + y*that.y, y*that.x - x*that.y }; } // A point on circle with specified radius Point radius( double r ) const { return Point{ x*r, y*r }; } // A point on circle with specified radius and circle center Point radius( const Point ¢er, double r ) const { return Point{ center.x + x*r, center.y + y*r }; } static Angle zero() { return Angle{ 1, 0 }; } static Angle pi() { return Angle{ -1, 0 }; } static Angle halfPi() { return Angle{ 0, 1 }; } }; int main() { Angle x( 7 * M_PI / 8 ); Angle y = x.half(); Angle y2( 7 * M_PI / 16 ); Angle x2 = y + y; Angle x3 = y.dbl(); return 0; }
to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.