Dandelion
2.0.0
A light-weight 3D builder for educational usage
Toggle main menu visibility
载入中...
搜索中...
未找到
math.hpp
浏览该文件的文档.
1
#ifndef DANDELION_UTILS_MATH_HPP
2
#define DANDELION_UTILS_MATH_HPP
3
4
#include <cmath>
5
#include <tuple>
6
7
#include <Eigen/Core>
8
9
/*!
10
* \ingroup utils
11
* \file utils/math.hpp
12
* \~chinese
13
* \brief 这个文件提供一些方便使用的数学函数。
14
*/
15
16
/*! \~chinese 由于 Eigen 的 Identity 方法返回的并非 Matrix 实例,在此创建一个含义相同的矩阵。 */
17
const
Eigen::Matrix3f
I3f
= Eigen::Matrix3f::Identity();
18
/*! \~chinese 由于 Eigen 的 Identity 方法返回的并非 Matrix 实例,在此创建一个含义相同的矩阵。 */
19
const
Eigen::Matrix4f
I4f
= Eigen::Matrix4f::Identity();
20
21
/*!
22
* \ingroup utils
23
* \~chinese
24
* \brief 返回 float 或 double 类型的 \f$\pi\f$ 值。
25
*/
26
template
<
typename
T>
27
T
pi
();
28
29
/*! \~chinese 返回 double 类型的特化。 */
30
template
<>
31
inline
constexpr
double
pi<double>
()
32
{
33
return
3.141592653589793238462643383279;
34
}
35
36
/*! \~chinese 返回 float 类型的特化。 */
37
template
<>
38
inline
constexpr
float
pi<float>
()
39
{
40
return
3.14159265358f;
41
}
42
43
/*!
44
* \ingroup utils
45
* \~chinese
46
* \brief 将角度转换为弧度。
47
*/
48
template
<
typename
T>
49
inline
constexpr
T
radians
(T
degrees
)
50
{
51
return
degrees
/
static_cast<
T
>
(180.0) *
pi<T>
();
52
}
53
54
/*!
55
* \ingroup utils
56
* \~chinese
57
* \brief 将弧度转换为角度。
58
*/
59
template
<
typename
T>
60
inline
constexpr
T
degrees
(T
radians
)
61
{
62
return
radians
/
pi<T>
() *
static_cast<
T
>
(180.0);
63
}
64
65
/*!
66
* \ingroup utils
67
* \~chinese
68
* \brief 求一个数的平方。
69
*/
70
template
<
typename
T>
71
inline
constexpr
T
squ
(T x)
72
{
73
return
x * x;
74
}
75
76
/*!
77
* \ingroup utils
78
* \~chinese
79
* \brief 将一个数截断在给定的上下界之间
80
*/
81
template
<
typename
T>
82
inline
constexpr
T
clamp
(T low, T high, T value)
83
{
84
return
std::max(low, std::min(high, value));
85
}
86
87
/*!
88
* \ingroup utils
89
* \~chinese
90
* \brief 将代表方向的三维向量转换为它的齐次坐标形式。
91
*
92
* 该函数在一个\f$3\times 1\f$的向量的末尾补 0 ,从而将其转换为\f$4\times 1\f$的方向向量。
93
* 如欲将三维的点转换为齐次坐标形式,请直接调用 `Eigen::Vector` 类型的 `homogeneous` 方法。
94
*/
95
template
<
typename
T>
96
inline
constexpr
Eigen::Vector<T, 4>
to_vec4
(Eigen::Vector<T, 3> vec3)
97
{
98
return
Eigen::Vector<T, 4>(vec3.x(), vec3.y(), vec3.z(),
static_cast<
T
>
(0.0));
99
}
100
101
/*!
102
* \ingroup utils
103
* \~chinese
104
* \brief 求向量 \f$\mathbf{I}\f$ 关于向量 \f$\mathbf{N}\f$ 的反射。
105
* \param I 表示入射射线的向量(不必是单位向量)
106
* \param N 反射平面的法线(必须是单位向量)
107
*/
108
inline
Eigen::Vector3f
reflect
(
const
Eigen::Vector3f& I,
const
Eigen::Vector3f& N)
109
{
110
return
I - 2 * I.dot(N) * N;
111
}
112
113
/*!
114
* \ingroup utils
115
* \~chinese
116
* \brief 符号函数,正数的求值结果为 1,负数为 -1,零的求值结果是 0.
117
*/
118
template
<
typename
T>
119
inline
constexpr
T sign(T x)
120
{
121
if
(x >
static_cast<
T
>
(0.0)) {
122
return
static_cast<
T
>
(1.0);
123
}
124
if
(x <
static_cast<
T
>
(0.0)) {
125
return
static_cast<
T
>
(-1.0);
126
}
127
return
static_cast<
T
>
(0.0);
128
}
129
130
/*!
131
* \ingroup utils
132
* \~chinese
133
* \brief 将旋转的四元数表示形式转换为 ZYX 欧拉角表示形式。
134
*
135
* 这个函数采用 ZYX 顺规(即依次绕自身 \f$z, y, x\f$ 轴旋转)。在 Dandelion
136
* 的坐标系约定下,ZYX 顺规对应 roll-yaw-pitch 旋转顺序(滚转、航向、俯仰)。
137
*
138
* 由于欧拉角固有的缺陷,这个函数并不能消除航向角(或称方向角 yaw)在 \f$\pm 90^\circ\f$
139
* 附近时产生的万向锁和抖动问题。
140
*
141
* 虽然函数的返回值是 `tuple`,但使用 `tuple` 接受返回值并不方便,建议用结构化绑定
142
* ```cpp
143
* auto [x_angle, y_angle, z_angle] = quaternion_to_ZYX_euler(w, x, y, z);
144
* ```
145
* 或 `std::tie` 来接受返回值。
146
*
147
* \returns 一个元组,它的三个分量依次是绕 x 轴、绕 y 轴和绕 z 轴的旋转角(角度制)。
148
*/
149
template
<
typename
T>
150
inline
std::tuple<T, T, T>
quaternion_to_ZYX_euler
(T w, T x, T y, T z)
151
{
152
const
T test = x * z + w * y;
153
constexpr
T threshold =
static_cast<
T
>
(0.5 - 1e-6);
154
T x_rad, y_rad, z_rad;
155
if
(std::abs(test) > threshold) {
156
x_rad =
static_cast<
T
>
(0.0);
157
y_rad = sign(test) *
pi<T>
() /
static_cast<
T
>
(2.0);
158
z_rad = sign(test) *
static_cast<
T
>
(2.0) * std::atan2(x, w);
159
}
else
{
160
x_rad =
161
std::atan2(
static_cast<
T
>
(-2.0) * (y * z - w * x),
squ
(w) -
squ
(x) -
squ
(y) +
squ
(z));
162
y_rad = std::asin(
static_cast<
T
>
(2.0) * (x * z + w * y));
163
z_rad =
164
std::atan2(
static_cast<
T
>
(-2.0) * (x * y - w * z),
squ
(w) +
squ
(x) -
squ
(y) -
squ
(z));
165
}
166
const
T x_angle =
degrees
(x_rad);
167
const
T y_angle =
degrees
(y_rad);
168
const
T z_angle =
degrees
(z_rad);
169
return
std::make_tuple(x_angle, y_angle, z_angle);
170
}
171
172
#endif
// DANDELION_UTILS_MATH_HPP
quaternion_to_ZYX_euler
std::tuple< T, T, T > quaternion_to_ZYX_euler(T w, T x, T y, T z)
将旋转的四元数表示形式转换为 ZYX 欧拉角表示形式。
定义
math.hpp:150
reflect
Eigen::Vector3f reflect(const Eigen::Vector3f &I, const Eigen::Vector3f &N)
求向量 关于向量 的反射。
定义
math.hpp:108
clamp
constexpr T clamp(T low, T high, T value)
将一个数截断在给定的上下界之间
定义
math.hpp:82
to_vec4
constexpr Eigen::Vector< T, 4 > to_vec4(Eigen::Vector< T, 3 > vec3)
将代表方向的三维向量转换为它的齐次坐标形式。
定义
math.hpp:96
degrees
constexpr T degrees(T radians)
将弧度转换为角度。
定义
math.hpp:60
pi
T pi()
返回 float 或 double 类型的 值。
squ
constexpr T squ(T x)
求一个数的平方。
定义
math.hpp:71
radians
constexpr T radians(T degrees)
将角度转换为弧度。
定义
math.hpp:49
I4f
const Eigen::Matrix4f I4f
定义
math.hpp:19
I3f
const Eigen::Matrix3f I3f
定义
math.hpp:17
src
utils
math.hpp
制作者
1.18.0