Reputation: 113
I have a 3x3 rotation matrix:
[ cos( angle ) sin( angle ) 0 ]
[ -sin( angle ) cos( angle ) 0 ]
[ 0 0 1 ]
How do I work out angle
?
The methods I'm using now to do this is:
void Mat3::SetAngle( const float angle ) {
m[ 0 + 0 * 3 ] = cos( angle );
m[ 1 + 0 * 3 ] = sin( angle );
m[ 0 + 1 * 3 ] = -sin( angle );
m[ 1 + 1 * 3 ] = cos( angle );
}
And to retreive it I'm using:
float Mat3::GetAngle( void ) {
return atan2( m[ 1 + 0 * 3], m[ 0 + 0 * 3] );
}
I'm testing it like this:
Mat3 m;
m.SetAngle( 179.0f );
float a = m.GetAngle();
And a ends up being 3.0708115 which is not correct.
Upvotes: 0
Views: 613
Reputation: 85
sin and cos take arguments in radians, while atan2 returns an angle in radians.
179 rad = 3.070811 + 14 * 2 * pi rad
which is the same angle as 3.070811 rad.
You could either pass in the required angle as radians and convert the GetAngle result
m.SetAngle( 179.0f * M_PI / 180.0f );
float a = m.GetAngle() * 180.0f / M_PI;
or modify the class to take degrees
void Mat3::SetAngle( const float angleDeg ) {
angleRad = angleDeg / 180.0f * M_PI;
m[ 0 + 0 * 3 ] = cos( angleRad );
// etc
}
float Mat3::GetAngle( void ) {
return atan2( m[ 1 + 0 * 3], m[ 0 + 0 * 3] ) * 180.0f / M_PI;
}
Either way I'd suggest documenting which unit your class expects.
Upvotes: 1
Reputation: 14164
Use an atan( sin/ cos)
function, or atan2( sin, cos)
if it's available.
The simple single-argument atan( s/c)
is the basic method. That answers angles from nearly -PI to +PI (approaching -90 degrees to approaching +90 degrees), but you will need to special-case a divide-by-0 at +/- 90 degrees exactly.
You also need to modify the result angle for "cosine(X) < 0", that is for the other 180 degrees of the circle.
See:
Upvotes: 0