1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_QUATERNION_H
17#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_QUATERNION_H
18
19#include "base/utils/utils.h"
20
21namespace OHOS::Ace {
22
23class Quaternion {
24public:
25    Quaternion() = default;
26    Quaternion(double x, double y, double z, double w) : x_(x), y_(y), z_(z), w_(w) {}
27    ~Quaternion() = default;
28
29    double GetX() const
30    {
31        return x_;
32    }
33    double GetY() const
34    {
35        return y_;
36    }
37    double GetZ() const
38    {
39        return z_;
40    }
41    double GetW() const
42    {
43        return w_;
44    }
45    void SetX(double x)
46    {
47        x_ = x;
48    }
49    void SetY(double y)
50    {
51        y_ = y;
52    }
53    void SetZ(double z)
54    {
55        z_ = z;
56    }
57    void SetW(double w)
58    {
59        w_ = w;
60    }
61
62    Quaternion operator+(const Quaternion& q) const
63    {
64        auto x = this->x_ + q.x_;
65        auto y = this->y_ + q.y_;
66        auto z = this->z_ + q.z_;
67        auto w = this->w_ + q.w_;
68        return Quaternion(x, y, z, w);
69    }
70
71    Quaternion operator*(const Quaternion& q) const
72    {
73        auto x = w_ * q.x_ + x_ * q.w_ + y_ * q.z_ - z_ * q.y_;
74        auto y = w_ * q.y_ - x_ * q.z_ + y_ * q.w_ + z_ * q.x_;
75        auto z = w_ * q.z_ + x_ * q.y_ - y_ * q.x_ + z_ * q.w_;
76        auto w = w_ * q.w_ - x_ * q.x_ - y_ * q.y_ - z_ * q.z_;
77        return Quaternion(x, y, z, w);
78    }
79
80    bool operator==(const Quaternion& q) const
81    {
82        return NearEqual(x_, q.x_) && NearEqual(y_, q.y_)
83            && NearEqual(z_, q.z_) && NearEqual(w_, q.w_);
84    }
85
86    bool operator!=(const Quaternion& q) const
87    {
88        return !operator==(q);
89    }
90
91    Quaternion inverse() const
92    {
93        return { -x_, -y_, -z_, w_ };
94    }
95
96    Quaternion flip() const
97    {
98        return { -x_, -y_, -z_, -w_ };
99    }
100
101    // Blends with the given quaternion, |q|, via spherical linear interpolation.
102    // Values of |t| in the range [0, 1] will interpolate between |this| and |q|,
103    // and values outside that range will extrapolate beyond in either direction.
104    Quaternion Slerp(const Quaternion& q, double t) const;
105
106private:
107    double x_ = 0.0;
108    double y_ = 0.0;
109    double z_ = 0.0;
110    double w_ = 0.0;
111};
112
113// |s| is an arbitrary, real constant.
114inline Quaternion operator*(const Quaternion& q, double s)
115{
116    return Quaternion(q.GetX() * s, q.GetY() * s, q.GetZ() * s, q.GetW() * s);
117}
118
119// |s| is an arbitrary, real constant.
120inline Quaternion operator*(double s, const Quaternion& q)
121{
122    return Quaternion(q.GetX() * s, q.GetY() * s, q.GetZ() * s, q.GetW() * s);
123}
124
125} // namespace OHOS::Ace
126
127#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_QUATERNION_H
128