// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_TRANSLATION_H
#define EIGEN_TRANSLATION_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

/** \geometry_module \ingroup Geometry_Module
 *
 * \class Translation
 *
 * \brief Represents a translation transformation
 *
 * \tparam Scalar_ the scalar type, i.e., the type of the coefficients.
 * \tparam Dim_ the dimension of the space, can be a compile time value or Dynamic
 *
 * \note This class is not aimed to be used to store a translation transformation,
 * but rather to make easier the constructions and updates of Transform objects.
 *
 * \sa class Scaling, class Transform
 */
template <typename Scalar_, int Dim_>
class Translation {
 public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar_, Dim_)
  /** dimension of the space */
  enum { Dim = Dim_ };
  /** the scalar type of the coefficients */
  using Scalar = Scalar_;
  /** corresponding vector type */
  using VectorType = Matrix<Scalar, Dim, 1>;
  /** corresponding linear transformation matrix type */
  using LinearMatrixType = Matrix<Scalar, Dim, Dim>;
  /** corresponding affine transformation type */
  using AffineTransformType = Transform<Scalar, Dim, Affine>;
  /** corresponding isometric transformation type */
  using IsometryTransformType = Transform<Scalar, Dim, Isometry>;

 protected:
  VectorType m_coeffs;

 public:
  /** Default constructor without initialization. */
  EIGEN_DEVICE_FUNC Translation() {}
  /**  */
  EIGEN_DEVICE_FUNC inline Translation(const Scalar& sx, const Scalar& sy) {
    eigen_assert(Dim == 2);
    m_coeffs.x() = sx;
    m_coeffs.y() = sy;
  }
  /**  */
  EIGEN_DEVICE_FUNC inline Translation(const Scalar& sx, const Scalar& sy, const Scalar& sz) {
    eigen_assert(Dim == 3);
    m_coeffs.x() = sx;
    m_coeffs.y() = sy;
    m_coeffs.z() = sz;
  }
  /** Constructs and initialize the translation transformation from a vector of translation coefficients */
  EIGEN_DEVICE_FUNC explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}

  /** \brief Returns the x-translation by value. **/
  EIGEN_DEVICE_FUNC constexpr Scalar x() const { return m_coeffs.x(); }
  /** \brief Returns the y-translation by value. **/
  EIGEN_DEVICE_FUNC constexpr Scalar y() const { return m_coeffs.y(); }
  /** \brief Returns the z-translation by value. **/
  EIGEN_DEVICE_FUNC constexpr Scalar z() const { return m_coeffs.z(); }

  /** \brief Returns the x-translation as a reference. **/
  EIGEN_DEVICE_FUNC constexpr Scalar& x() { return m_coeffs.x(); }
  /** \brief Returns the y-translation as a reference. **/
  EIGEN_DEVICE_FUNC constexpr Scalar& y() { return m_coeffs.y(); }
  /** \brief Returns the z-translation as a reference. **/
  EIGEN_DEVICE_FUNC constexpr Scalar& z() { return m_coeffs.z(); }

  EIGEN_DEVICE_FUNC const VectorType& vector() const { return m_coeffs; }
  EIGEN_DEVICE_FUNC VectorType& vector() { return m_coeffs; }

  EIGEN_DEVICE_FUNC const VectorType& translation() const { return m_coeffs; }
  EIGEN_DEVICE_FUNC VectorType& translation() { return m_coeffs; }

  /** Concatenates two translations */
  EIGEN_DEVICE_FUNC inline Translation operator*(const Translation& other) const {
    return Translation(m_coeffs + other.m_coeffs);
  }

  /** Concatenates a translation and a uniform scaling */
  EIGEN_DEVICE_FUNC inline AffineTransformType operator*(const UniformScaling<Scalar>& other) const;

  /** Concatenates a translation and a linear transformation */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC inline AffineTransformType operator*(const EigenBase<OtherDerived>& linear) const;

  /** Concatenates a translation and a rotation */
  template <typename Derived>
  EIGEN_DEVICE_FUNC inline IsometryTransformType operator*(const RotationBase<Derived, Dim>& r) const {
    return *this * IsometryTransformType(r);
  }

  /** \returns the concatenation of a linear transformation \a l with the translation \a t */
  // it's a nightmare to define a templated friend function outside its declaration
  template <typename OtherDerived>
  friend EIGEN_DEVICE_FUNC inline AffineTransformType operator*(const EigenBase<OtherDerived>& linear,
                                                                const Translation& t) {
    AffineTransformType res;
    res.matrix().setZero();
    res.linear() = linear.derived();
    res.translation() = linear.derived() * t.m_coeffs;
    res.matrix().row(Dim).setZero();
    res(Dim, Dim) = Scalar(1);
    return res;
  }

  /** Concatenates a translation and a transformation */
  template <int Mode, int Options>
  EIGEN_DEVICE_FUNC inline Transform<Scalar, Dim, Mode> operator*(
      const Transform<Scalar, Dim, Mode, Options>& t) const {
    Transform<Scalar, Dim, Mode> res = t;
    res.pretranslate(m_coeffs);
    return res;
  }

  /** Applies translation to vector */
  template <typename Derived>
  inline std::enable_if_t<Derived::IsVectorAtCompileTime, VectorType> operator*(const MatrixBase<Derived>& vec) const {
    return m_coeffs + vec.derived();
  }

  /** \returns the inverse translation (opposite) */
  Translation inverse() const { return Translation(-m_coeffs); }

  static const Translation Identity() { return Translation(VectorType::Zero()); }

  /** \returns \c *this with scalar type casted to \a NewScalarType
   *
   * Note that if \a NewScalarType is equal to the current scalar type of \c *this
   * then this function smartly returns a const reference to \c *this.
   */
  template <typename NewScalarType>
  EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Translation, Translation<NewScalarType, Dim> >::type
  cast() const {
    return typename internal::cast_return_type<Translation, Translation<NewScalarType, Dim> >::type(*this);
  }

  /** Copy constructor with scalar type conversion */
  template <typename OtherScalarType>
  EIGEN_DEVICE_FUNC inline explicit Translation(const Translation<OtherScalarType, Dim>& other) {
    m_coeffs = other.vector().template cast<Scalar>();
  }

  /** \returns \c true if \c *this is approximately equal to \a other, within the precision
   * determined by \a prec.
   *
   * \sa MatrixBase::isApprox() */
  EIGEN_DEVICE_FUNC bool isApprox(const Translation& other, const typename NumTraits<Scalar>::Real& prec =
                                                                NumTraits<Scalar>::dummy_precision()) const {
    return m_coeffs.isApprox(other.m_coeffs, prec);
  }
};

/** \addtogroup Geometry_Module */
//@{
using Translation2f = Translation<float, 2>;
using Translation2d = Translation<double, 2>;
using Translation3f = Translation<float, 3>;
using Translation3d = Translation<double, 3>;
//@}

template <typename Scalar, int Dim>
EIGEN_DEVICE_FUNC inline typename Translation<Scalar, Dim>::AffineTransformType Translation<Scalar, Dim>::operator*(
    const UniformScaling<Scalar>& other) const {
  AffineTransformType res;
  res.matrix().setZero();
  res.linear().diagonal().fill(other.factor());
  res.translation() = m_coeffs;
  res(Dim, Dim) = Scalar(1);
  return res;
}

template <typename Scalar, int Dim>
template <typename OtherDerived>
EIGEN_DEVICE_FUNC inline typename Translation<Scalar, Dim>::AffineTransformType Translation<Scalar, Dim>::operator*(
    const EigenBase<OtherDerived>& linear) const {
  AffineTransformType res;
  res.matrix().setZero();
  res.linear() = linear.derived();
  res.translation() = m_coeffs;
  res.matrix().row(Dim).setZero();
  res(Dim, Dim) = Scalar(1);
  return res;
}

}  // end namespace Eigen

#endif  // EIGEN_TRANSLATION_H
