Skip to content

File proper_quaternion.hpp

File List > data_format > proper_quaternion.hpp

Go to the documentation of this file

#pragma once
#ifdef __ANDROID__
#    include 
#else
#    include 
#endif
#include 

namespace ILLIXR::data_format {

template<typename Scalar_, int Options_ = Eigen::AutoAlign>
class proper_quaternion : public Eigen::Quaternion<Scalar_, Options_> {
public:
    typedef typename Eigen::Quaternion<Scalar_>::Base Base;

    using Base::operator=;

    inline proper_quaternion& operator=(const proper_quaternion& other) {
        Base::operator=(other);
        return *this;
    }

    using Base::operator*=;

    // constructors
    proper_quaternion()                               = default;
    proper_quaternion(const proper_quaternion& other) = default;

    [[maybe_unused]] explicit proper_quaternion(const Eigen::Quaternion<Scalar_, Options_>& other)
        : Eigen::Quaternion<Scalar_, Options_>(other) { }

    [[maybe_unused]] proper_quaternion(const Scalar_& w, const Scalar_& x, const Scalar_& y, const Scalar_& z)
        : Eigen::Quaternion<Scalar_, Options_>(w, x, y, z) { }

    template<typename Derived>
    [[maybe_unused]] proper_quaternion(const Scalar_& w, const Eigen::MatrixBase<Derived>& vec)
        : Eigen::Quaternion<Scalar_, Options_>(w, vec) { }

    [[maybe_unused]] explicit proper_quaternion(const Scalar_* data)
        : Eigen::Quaternion<Scalar_, Options_>(data) { }

    [[maybe_unused]] explicit proper_quaternion(const Eigen::Matrix<Scalar_, 4, 1>& vec)
        : Eigen::Quaternion<Scalar_, Options_>(vec[3], vec[0], vec[1], vec[2]) { }

    template<typename Derived>
    [[maybe_unused]] explicit proper_quaternion(const Eigen::QuaternionBase<Derived>& other)
        : Eigen::Quaternion<Scalar_>(other) { }

    proper_quaternion& operator*=(const Scalar_& a) {
        this->x() *= a;
        this->y() *= a;
        this->z() *= a;
        this->w() *= a;
        return *this;
    }

    proper_quaternion operator*(const int a) const {
        return proper_quaternion<Scalar_, Options_>(this->w() * a, this->x() * a, this->y() * a, this->z() * a);
    }

    proper_quaternion operator*(const float a) const {
        return proper_quaternion<Scalar_, Options_>(this->w() * a, this->x() * a, this->y() * a, this->z() * a);
    }

    proper_quaternion operator*(const double a) const {
        return proper_quaternion<Scalar_, Options_>(this->w() * a, this->x() * a, this->y() * a, this->z() * a);
    }

    proper_quaternion<Scalar_> operator*(const Eigen::Quaternion<Scalar_>& other) const {
        return proper_quaternion<Scalar_>(Eigen::Quaternion<Scalar_>::operator*(other));
    }

    Eigen::Matrix<Scalar_, 4, 1> asVector() const {
        return Eigen::Matrix<Scalar_, 4, 1>(this->x(), this->y(), this->z(), this->w());
    }

    proper_quaternion<Scalar_>& operator+=(const proper_quaternion<Scalar_>& other) {
        this->w() += other.w();
        this->x() += other.x();
        this->y() += other.y();
        this->z() += other.z();
        return *this;
    }

    proper_quaternion<Scalar_> operator+(const proper_quaternion<Scalar_>& other) const {
        proper_quaternion<Scalar_> result(*this);
        result += other;
        return result;
    }

    template<typename T>
    proper_quaternion<T> cast() {
        return proper_quaternion<T>(static_cast<T>(this->w()), static_cast<T>(this->x()), static_cast<T>(this->y()),
                                    static_cast<T>(this->z()));
    }

    inline void normalize() {
        if (this->w() < 0.)
            (*this) *= -1.;

        Eigen::Quaternion<Scalar_, Options_>::normalize();
    }
};

template<typename T>
std::ostream& operator<<(std::ostream& os, const proper_quaternion<T>& pq) {
    os << "X " << pq.x() << std::endl << "Y " << pq.y() << std::endl << "Z " << pq.z() << std::endl << "W " << pq.w();
    return os;
}

[[maybe_unused]] typedef proper_quaternion<double> proper_quaterniond;
[[maybe_unused]] typedef proper_quaternion<float>  proper_quaternionf;

template<typename Scalar_>
inline proper_quaternion<Scalar_> operator*(Scalar_ x, const proper_quaternion<Scalar_>& pq) {
    return proper_quaternion<Scalar_>(x * pq.w(), x * pq.x(), x * pq.y(), x * pq.z());
}

template<typename Scalar_>
inline proper_quaternion<Scalar_> operator/(const proper_quaternion<Scalar_>& pq, Scalar_ x) {
    return proper_quaternion<Scalar_>(pq.w() / x, pq.x() / x, pq.y() / x, pq.z() / x);
}

} // namespace ILLIXR::data_format