use Matrix;
use FRAC_PI_2;
// use super::Quaternion;
// @short_description: Functions for initializing and manipulating
// euler angles.
//
// Euler angles are a simple representation of a 3 dimensional
// rotation; comprised of 3 ordered heading, pitch and roll rotations.
// An important thing to understand is that the axis of rotation
// belong to the object being rotated and so they also rotate as each
// of the heading, pitch and roll rotations are applied.
//
// One way to consider euler angles is to imagine controlling an
// aeroplane, where you first choose a heading (Such as flying south
// east), then you set the pitch (such as 30 degrees to take off) and
// then you might set a roll, by dipping the left, wing as you prepare
// to turn.
//
// They have some advantages and limitations that it helps to be
// aware of:
//
// Advantages:
// <itemizedlist>
// -
// Easy to understand and use, compared to quaternions and matrices,
// so may be a good choice for a user interface.
// </listitem>
// -
// Efficient storage, needing only 3 components any rotation can be
// represented.
// Actually the #Euler type isn't optimized for size because
// we may cache the equivalent #Quaternion along with a euler
// rotation, but it would be trivial for an application to track the
// components of euler rotations in a packed float array if optimizing
// for size was important. The values could be passed to only when
// manipulation is necessary.
// </listitem>
// </itemizedlist>
//
// Disadvantages:
// <itemizedlist>
// -
// Aliasing: it's possible to represent some rotations with multiple
// different heading, pitch and roll rotations.
// </listitem>
// -
// They can suffer from a problem called Gimbal Lock. A good
// explanation of this can be seen on wikipedia here:
// http://en.wikipedia.org/wiki/Gimbal_lock but basically two
// of the axis of rotation may become aligned and so you loose a
// degree of freedom. For example a pitch of +-90° would mean that
// heading and bank rotate around the same axis.
// </listitem>
// -
// If you use euler angles to orient something in 3D space and try to
// transition between orientations by interpolating the component
// angles you probably wont get the transitions you expect as they may
// not follow the shortest path between the two orientations.
// </listitem>
// -
// There's no standard to what order the component axis rotations are
// applied. The most common convention seems to be what we do in
// with heading (y-axis), pitch (x-axis) and then roll (z-axis), but
// other software might apply x-axis, y-axis then z-axis or any other
// order so you need to consider this if you are accepting euler
// rotations from some other software. Other software may also use
// slightly different aeronautical terms, such as "yaw" instead of
// "heading" or "bank" instead of "roll".
// </listitem>
// </itemizedlist>
//
// To minimize the aliasing issue we may refer to "Canonical Euler"
// angles where heading and roll are restricted to +- 180° and pitch is
// restricted to +- 90°. If pitch is +- 90° bank is set to 0°.
//
// Quaternions don't suffer from Gimbal Lock and they can be nicely
// interpolated between, their disadvantage is that they don't have an
// intuitive representation.
//
// A common practice is to accept angles in the intuitive Euler form
// and convert them to quaternions internally to avoid Gimbal Lock and
// handle interpolations. See quaternion_init_from_euler().
// Euler:
// @heading: Angle to rotate around an object's y axis
// @pitch: Angle to rotate around an object's x axis
// @roll: Angle to rotate around an object's z axis
//
// Represents an ordered rotation first of @heading degrees around an
// object's y axis, then @pitch degrees around an object's x axis and
// finally @roll degrees around an object's z axis.
//
// It's important to understand the that axis are associated
// with the object being rotated, so the axis also rotate in sequence
// with the rotations being applied.
//
// The members of a #Euler can be initialized, for example, with
// euler_init() and euler_init_from_quaternion ().
//
// You may also want to look at quaternion_init_from_euler() if
// you want to do interpolation between 3d rotations.
// Hash