// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#ifndef EIGEN_EULERANGLES_H
#define EIGEN_EULERANGLES_H

template<typename Other,
         int OtherRows=Other::RowsAtCompileTime,
         int OtherCols=Other::ColsAtCompileTime>
struct ei_eulerangles_assign_impl;

// enum {
//   XYZ,
//   XYX,
//
//
// };

/** \class EulerAngles
  *
  * \brief Represents a rotation in a 3 dimensional space as three Euler angles
  *
  * \param _Scalar the scalar type, i.e., the type of the angles.
  *
  * \sa class Quaternion, class AngleAxis, class Transform
  */
template<typename _Scalar>
class EulerAngles
{
public:
  enum { Dim = 3 };
  /** the scalar type of the coefficients */
  typedef _Scalar Scalar;
  typedef Matrix<Scalar,3,3> Matrix3;
  typedef Matrix<Scalar,3,1> Vector3;
  typedef Quaternion<Scalar> QuaternionType;
  typedef AngleAxis<Scalar> AngleAxisType;

protected:

  Vector3 m_angles;

public:

  EulerAngles() {}
  inline EulerAngles(Scalar a0, Scalar a1, Scalar a2) : m_angles(a0, a1, a2) {}
  inline EulerAngles(const QuaternionType& q) { *this = q; }
  inline EulerAngles(const AngleAxisType& aa) { *this = aa; }
  template<typename Derived>
  inline EulerAngles(const MatrixBase<Derived>& m) { *this = m; }

  Scalar angle(int i) const { return m_angles.coeff(i); }
  Scalar& angle(int i) { return m_angles.coeffRef(i); }

  const Vector3& coeffs() const { return m_angles; }
  Vector3& coeffs() { return m_angles; }

  EulerAngles& operator=(const QuaternionType& q);
  EulerAngles& operator=(const AngleAxisType& ea);
  template<typename Derived>
  EulerAngles& operator=(const MatrixBase<Derived>& m);

  template<typename Derived>
  EulerAngles& fromRotationMatrix(const MatrixBase<Derived>& m);
  Matrix3 toRotationMatrix(void) const;
};

/** Set \c *this from a quaternion.
  * The axis is normalized.
  */
template<typename Scalar>
EulerAngles<Scalar>& EulerAngles<Scalar>::operator=(const QuaternionType& q)
{
  Scalar y2 = q.y() * q.y();
  m_angles.coeffRef(0) = std::atan2(2*(q.w()*q.x() + q.y()*q.z()), (1 - 2*(q.x()*q.x() + y2)));
  m_angles.coeffRef(1) = std::asin( 2*(q.w()*q.y() - q.z()*q.x()));
  m_angles.coeffRef(2) = std::atan2(2*(q.w()*q.z() + q.x()*q.y()), (1 - 2*(y2 + q.z()*q.z())));
  return *this;
}

/** Set \c *this from Euler angles \a ea.
  */
template<typename Scalar>
EulerAngles<Scalar>& EulerAngles<Scalar>::operator=(const AngleAxisType& aa)
{
  return *this = QuaternionType(aa);
}

/** Set \c *this from the expression \a xpr:
  *   - if \a xpr is a 3x1 vector, then \a xpr is assumed to be a vector of angles
  *   - if \a xpr is a 3x3 matrix, then \a xpr is assumed to be rotation matrix
  *     and \a xpr is converted to Euler angles
  */
template<typename Scalar>
template<typename Derived>
EulerAngles<Scalar>& EulerAngles<Scalar>::operator=(const MatrixBase<Derived>& other)
{
  ei_eulerangles_assign_impl<Derived>::run(*this,other.derived());
  return *this;
}

/** Constructs and \returns an equivalent 3x3 rotation matrix.
  */
template<typename Scalar>
typename EulerAngles<Scalar>::Matrix3
EulerAngles<Scalar>::toRotationMatrix(void) const
{
  Vector3 c = m_angles.cwise().cos();
  Vector3 s = m_angles.cwise().sin();
  return Matrix3() <<
    c.y()*c.z(),                    -c.y()*s.z(),                   s.y(),
    c.z()*s.x()*s.y()+c.x()*s.z(),  c.x()*c.z()-s.x()*s.y()*s.z(),  -c.y()*s.x(),
    -c.x()*c.z()*s.y()+s.x()*s.z(), c.z()*s.x()+c.x()*s.y()*s.z(),  c.x()*c.y();
}

// set from a rotation matrix
template<typename Other>
struct ei_eulerangles_assign_impl<Other,3,3>
{
  typedef typename Other::Scalar Scalar;
  inline static void run(EulerAngles<Scalar>& ea, const Other& mat)
  {
    // mat =  cy*cz          -cy*sz           sy
    //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
    //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
    ea.angle(1) = std::asin(mat.coeff(0,2));
    ea.angle(0) = std::atan2(-mat.coeff(1,2),mat.coeff(2,2));
    ea.angle(2) = std::atan2(-mat.coeff(0,1),mat.coeff(0,0));
  }
};

// set from a vector of angles
template<typename Other>
struct ei_eulerangles_assign_impl<Other,3,1>
{
  typedef typename Other::Scalar Scalar;
  inline static void run(EulerAngles<Scalar>& ea, const Other& vec)
  {
    ea.coeffs() = vec;
  }
};

#endif // EIGEN_EULERANGLES_H
