This commit is contained in:
zd383321154 2025-05-28 23:12:57 +08:00
parent c8b1414fca
commit 83cb70bec9
2 changed files with 98 additions and 1 deletions

View File

@ -12,13 +12,18 @@
#include <simgear/math/simd.hxx>
/// 2D Vector Class
//SGVec2类是一个2D向量类定义了2D向量的基本操作和运算
template<typename T>
class SGVec2 {
public:
//定义一个类型别名value_type表示向量中的元素类型
// C++11可以使用 using value_type = T;
typedef T value_type;
/// Default constructor. Does not initialize at all.
/// If you need them zero initialized, use SGVec2::zeros()
//默认构造函数,不进行初始化
//如果需要零初始化可以使用SGVec2::zeros()
SGVec2(void)
{
/// Initialize with nans in the debug build, that will guarantee to have
@ -30,84 +35,110 @@ public:
#endif
}
/// Constructor. Initialize by the given values
//构造函数,初始化为给定的值
SGVec2(T x, T y)
{ _data = simd4_t<T,2>(x, y); }
/// Constructor. Initialize by the content of a plain array,
/// make sure it has at least 2 elements
//构造函数使用一个包含2个元素的数组初始化
//确保数组至少有2个元素
explicit SGVec2(const T* d)
{ _data = d ? simd4_t<T,2>(d) : simd4_t<T,2>(T(0)); }
//模板构造函数使用另一个SGVec2<S>类型的二维向量初始化
template<typename S>
explicit SGVec2(const SGVec2<S>& d)
{ data()[0] = d[0]; data()[1] = d[1]; }
/// Access by index, the index is unchecked
//小括号运算符重载,通过索引访问向量元素的常量引用,索引未检查
const T& operator()(unsigned i) const
{ return data()[i]; }
/// Access by index, the index is unchecked
//小括号运算符重载,通过索引访问向量元素的引用,索引未检查
T& operator()(unsigned i)
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
//中括号运算符重载,通过索引访问向量元素的常量引用,索引未检查
const T& operator[](unsigned i) const
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
//中括号运算符重载,通过索引访问向量元素的引用,索引未检查
T& operator[](unsigned i)
{ return data()[i]; }
/// Access the x component
//x()函数返回向量的x分量的常量引用
const T& x(void) const
{ return data()[0]; }
/// Access the x component
//x()函数返回向量的x分量的引用
T& x(void)
{ return data()[0]; }
/// Access the y component
//y()函数返回向量的y分量的常量引用
const T& y(void) const
{ return data()[1]; }
/// Access the y component
//y()函数返回向量的y分量的引用
T& y(void)
{ return data()[1]; }
/// Access raw data
//返回一个实际数组的常量引用是一个2个元素的数组
const T (&data(void) const)[2]
{ return _data.ptr(); }
/// Access raw data
//返回一个实际数组的引用是一个2个元素的数组
T (&data(void))[2]
{ return _data.ptr(); }
//返回一个simd4_t<T,2>类型的常量引用表示一个2D向量
const simd4_t<T,2> &simd2(void) const
{ return _data; }
/// Readonly raw storage interface
//返回一个simd4_t<T,2>类型的引用表示一个2D向量
simd4_t<T,2> &simd2(void)
{ return _data; }
/// Inplace addition
//+=运算符重载,实现向量加法
SGVec2& operator+=(const SGVec2& v)
{ _data += v.simd2(); return *this; }
/// Inplace subtraction
//-=运算符重载,实现向量减法
SGVec2& operator-=(const SGVec2& v)
{ _data -= v.simd2(); return *this; }
/// Inplace scalar multiplication
//*=运算符重载,实现向量乘法
template<typename S>
SGVec2& operator*=(S s)
{ _data *= s; return *this; }
/// Inplace scalar multiplication by 1/s
// /=运算符重载,实现向量除法
template<typename S>
SGVec2& operator/=(S s)
{ _data*=(1/T(s)); return *this; }
/// Return an all zero vector
//zeros()函数,返回一个零向量
static SGVec2 zeros(void)
{ return SGVec2(0, 0); }
/// Return unit vectors
//e1()函数返回一个x=1,y=0的向量
static SGVec2 e1(void)
{ return SGVec2(1, 0); }
//e2()函数返回一个x=0,y=1的向量
static SGVec2 e2(void)
{ return SGVec2(0, 1); }
private:
//_data是一个simd4_t<T,2>类型的成员变量表示一个2D向量
simd4_t<T,2> _data;
};
// 以下是一些运算符的类外重载
/// Unary +, do nothing ...
//一元+运算符重载,什么都不做
template<typename T>
inline
const SGVec2<T>&
@ -115,6 +146,7 @@ operator+(const SGVec2<T>& v)
{ return v; }
/// Unary -, do nearly nothing
//一元-运算符重载,对向量取反[-x,-y]
template<typename T>
inline
SGVec2<T>
@ -122,6 +154,7 @@ operator-(SGVec2<T> v)
{ v *= -1; return v; }
/// Binary +
//二元+运算符重载,实现向量加法[x1+x2,y1+y2]
template<typename T>
inline
SGVec2<T>
@ -129,6 +162,7 @@ operator+(SGVec2<T> v1, const SGVec2<T>& v2)
{ v1.simd2() += v2.simd2(); return v1; }
/// Binary -
//二元-运算符重载,实现向量减法[x1-x2,y1-y2]
template<typename T>
inline
SGVec2<T>
@ -136,6 +170,7 @@ operator-(SGVec2<T> v1, const SGVec2<T>& v2)
{ v1.simd2() -= v2.simd2(); return v1; }
/// Scalar multiplication
//标量乘法运算符重载,实现向量左数乘[s*x1,s*y1]
template<typename S, typename T>
inline
SGVec2<T>
@ -143,6 +178,7 @@ operator*(S s, SGVec2<T> v)
{ v.simd2() *= s; return v; }
/// Scalar multiplication
//标量乘法运算符重载,实现向量右数乘[x1*s,y1*s]
template<typename S, typename T>
inline
SGVec2<T>
@ -152,6 +188,9 @@ operator*(SGVec2<T> v, S s)
/// multiplication as a multiplicator, that is assume that the first vector
/// represents a 2x2 diagonal matrix with the diagonal elements in the vector.
/// Then the result is the product of that matrix times the second vector.
/// 作为乘数的乘法运算,即假设第一个向量
/// 表示一个2x2的对角矩阵其对角线元素就是向量中的元素。
/// 然后结果是该矩阵与第二个向量的乘积。即向量对应位置相乘[x1*x2,y1*y2]
template<typename T>
inline
SGVec2<T>
@ -159,16 +198,21 @@ mult(SGVec2<T> v1, const SGVec2<T>& v2)
{ v1.simd2() *= v2.simd2(); return v1; }
/// component wise min
//向量分量求最小值运算,实现向量分量最小值运算[min(x1,x2),min(y1,y2)]
template<typename T>
inline
SGVec2<T>
min(SGVec2<T> v1, const SGVec2<T>& v2)
{ v1.simd2() = simd4::min(v1.simd2(), v2.simd2()); return v1; }
//向量分量与右侧标量求最小值运算,实现向量分量与标量最小值运算[min(x,s),min(y,s)]
template<typename S, typename T>
inline
SGVec2<T>
min(SGVec2<T> v, S s)
{ v.simd2() = simd4::min(v.simd2(), simd4_t<T,2>(s)); return v; }
//向量分量与左侧标量求最小值运算,实现向量分量与标量最小值运算[min(s,x),min(s,y)]
template<typename S, typename T>
inline
SGVec2<T>
@ -176,16 +220,21 @@ min(S s, SGVec2<T> v)
{ v.sim2() = simd4::min(v.simd2(), simd4_t<T,2>(s)); return v; }
/// component wise max
//向量分量求最大值运算,实现向量分量最大值运算[max(x1,x2),max(y1,y2)]
template<typename T>
inline
SGVec2<T>
max(SGVec2<T> v1, const SGVec2<T>& v2)
{ v1.simd2() = simd4::max(v1.simd2(), v2.simd2()); return v1; }
//向量分量与右侧标量求最大值运算,实现向量分量与标量最大值运算[max(x,s),max(y,s)]
template<typename S, typename T>
inline
SGVec2<T>
max(const SGVec2<T>& v, S s)
{ v = simd4::max(v.simd2(), simd4_t<T,2>(s)); return v; }
//向量分量与左侧标量求最大值运算,实现向量分量与标量最大值运算[max(s,x),max(s,y)]
template<typename S, typename T>
inline
SGVec2<T>
@ -194,6 +243,7 @@ max(S s, const SGVec2<T>& v)
/// Add two vectors taking care of (integer) overflows. The values are limited
/// to the respective minimum and maximum values.
//向量分量无溢出求和运算,实现向量分量求和[x1+x2,y1+y2]
template<class T>
SGVec2<T> addClipOverflow(SGVec2<T> const& lhs, SGVec2<T> const& rhs)
{
@ -204,6 +254,7 @@ SGVec2<T> addClipOverflow(SGVec2<T> const& lhs, SGVec2<T> const& rhs)
}
/// Scalar dot product
//向量点积运算,实现向量点积运算 x1*x2+y1*y2
template<typename T>
inline
T
@ -211,6 +262,7 @@ dot(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return simd4::dot(v1.simd2(), v2.simd2()); }
/// The euclidean norm of the vector, that is what most people call length
//向量二范数运算,实现向量二范数运算 sqrt(x^2+y^2)
template<typename T>
inline
T
@ -219,6 +271,7 @@ norm(const SGVec2<T>& v)
/// The squared euclidean norm of the vector
/// Comparing two squared values prevents two computionally heavy sqrt calls.
//向量二范数平方运算,实现向量二范数平方运算 (x^2+y^2)
template<typename T>
inline
T
@ -226,6 +279,7 @@ norm2(const SGVec2<T>& v)
{ return simd4::magnitude2(v.simd2()); }
/// The euclidean norm of the vector, that is what most people call length
//向量长度运算,实现向量长度运算,与二范数相同 sqrt(x^2+y^2)
template<typename T>
inline
T
@ -234,6 +288,7 @@ length(const SGVec2<T>& v)
/// The 1-norm of the vector, this one is the fastest length function we
/// can implement on modern cpu's
//向量一范数运算,实现向量一范数运算 |x|+|y|
template<typename T>
inline
T
@ -241,6 +296,7 @@ norm1(SGVec2<T> v)
{ v.simd2() = simd4::abs(v.simd2()); return (v(0)+v(1)); }
/// The inf-norm of the vector
//向量无穷范数运算,实现向量无穷范数运算 max(|x|,|y|)
template<typename T>
inline
T
@ -251,6 +307,7 @@ normI(SGVec2<T> v)
}
/// The euclidean norm of the vector, that is what most people call length
//向量归一化运算,实现向量归一化运算,即向量除以其长度 [x/sqrt(x^2+y^2),y/sqrt(x^2+y^2)]
template<typename T>
inline
SGVec2<T>
@ -263,6 +320,7 @@ normalize(const SGVec2<T>& v)
}
/// Return true if exactly the same
//向量相等判断运算符重载,实现向量相等判断 x1==x2 && y1==y2
template<typename T>
inline
bool
@ -270,6 +328,7 @@ operator==(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return v1(0) == v2(0) && v1(1) == v2(1); }
/// Return true if not exactly the same
//向量不相等判断运算符重载,实现向量不相等判断 x1!=x2 || y1!=y2
template<typename T>
inline
bool
@ -277,6 +336,7 @@ operator!=(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return ! (v1 == v2); }
/// Return true if smaller, good for putting that into a std::map
//向量小于判断运算符重载,实现向量小于判断 x1<x2 || (x1==x2 && y1<y2)
template<typename T>
inline
bool
@ -287,6 +347,7 @@ operator<(const SGVec2<T>& v1, const SGVec2<T>& v2)
else return (v1(1) < v2(1));
}
//向量小于等于判断运算符重载,实现向量小于等于判断 x1<=x2 || (x1==x2 && y1<=y2)
template<typename T>
inline
bool
@ -297,12 +358,14 @@ operator<=(const SGVec2<T>& v1, const SGVec2<T>& v2)
else return (v1(1) <= v2(1));
}
//向量大于判断运算符重载,实现向量大于判断 x1>x2 || (x1==x2 && y1>y2)
template<typename T>
inline
bool
operator>(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return operator<(v2, v1); }
//向量大于等于判断运算符重载,实现向量大于等于判断 x1>=x2 || (x1==x2 && y1>=y2)
template<typename T>
inline
bool
@ -310,6 +373,14 @@ operator>=(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return operator<=(v2, v1); }
/// Return true if equal to the relative tolerance tol
// 判断两个二维向量是否在给定误差范围内相等,
// rtol: 相对误差容限relative tolerance
// atol: 绝对误差容限absolute tolerance
// 这种比较方式特别适用于:
// 1. 处理浮点数计算中的舍入误差
// 2. 当向量的分量值很大时,允许有更大的绝对误差(通过相对误差项)
// 3. 当向量的分量值很小时,通过绝对误差项来避免过于严格的比较
// 这比简单的相等比较(==)更实用,因为在计算机的浮点数运算中,由于舍入误差,很少有两个浮点数完全相等的情况。
template<typename T>
inline
bool
@ -317,6 +388,9 @@ equivalent(const SGVec2<T>& v1, const SGVec2<T>& v2, T rtol, T atol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)) + atol; }
/// Return true if equal to the relative tolerance tol
// 判断两个二维向量是否在给定相对误差容限下相等,
// rtol: 相对误差容限relative tolerance
// 适用于不需要考虑绝对误差的场景
template<typename T>
inline
bool
@ -324,6 +398,8 @@ equivalent(const SGVec2<T>& v1, const SGVec2<T>& v2, T rtol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)); }
/// Return true if about equal to roundoff of the underlying type
// 判断两个二维向量是否在默认的绝对误差容限和相对误差容限下相等,
// 默认绝对误差容限和默认相对误差容限为100倍的机器精度epsilon
template<typename T>
inline
bool
@ -334,6 +410,7 @@ equivalent(const SGVec2<T>& v1, const SGVec2<T>& v2)
}
/// The euclidean distance of the two vectors
// 计算两个二维向量之间的欧几里得距离 sqrt((x1-x2)^2+(y1-y2)^2)
template<typename T>
inline
T
@ -341,6 +418,7 @@ dist(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return simd4::magnitude(v1.simd2() - v2.simd2()); }
/// The squared euclidean distance of the two vectors
// 计算两个二维向量之间的欧几里得距离的平方 (x1-x2)^2+(y1-y2)^2
template<typename T>
inline
T
@ -348,6 +426,9 @@ distSqr(SGVec2<T> v1, const SGVec2<T>& v2)
{ return simd4::magnitude2(v1.simd2() - v2.simd2()); }
// calculate the projection of u along the direction of d.
// 计算向量u在向量d方向上的投影 d * (dot(u, d) / norm2(d))
// 这里的判断SGLimits<T>::min() < denom应该有问题为了避免除以0应该判断denom <= SGLimits<T>::min()
template<typename T>
inline
SGVec2<T>
@ -355,10 +436,12 @@ projection(const SGVec2<T>& u, const SGVec2<T>& d)
{
T denom = simd4::magnitude2(d.simd2());
T ud = dot(u, d);
if (SGLimits<T>::min() < denom) return u;
//if (SGLimits<T>::min() < denom) return u;
if (denom <= SGLimits<T>::min()) return u; //这里改了一下
else return d * (dot(u, d) / denom);
}
// 计算两个二维向量之间的线性插值tau在[0,1]之间
template<typename T>
inline
SGVec2<T>
@ -370,6 +453,11 @@ interpolate(T tau, const SGVec2<T>& v1, const SGVec2<T>& v2)
}
// Helper function for point_in_triangle
// 用于计算三个点构成的有向面积signed area它是判断点是否在三角形内的辅助函数。
//正值:表示三个点按逆时针方向排列
//负值:表示三个点按顺时针方向排列
//零值:表示三点共线
template <typename T>
inline
T
@ -379,6 +467,10 @@ pt_determine(const SGVec2<T>& pt1, const SGVec2<T>& pt2, const SGVec2<T>& pt3)
}
// Is testpt inside the triangle formed by the other three points?
// 判断点testpt是否在三角形内
// 如果一个点在三角形内部,那么它与三角形任意两个顶点形成的有向面积的符号应该都相同(要么都是正的,要么都是负的)
// 如果一个点在三角形外部,那么它与三角形任意两个顶点形成的有向面积的符号应该相反(一个为正,一个为负)
// 如果一个点在三角形边上那么它与三角形任意两个顶点形成的有向面积的符号应该为0
template <typename T>
inline
bool
@ -392,6 +484,7 @@ point_in_triangle(const SGVec2<T>& testpt, const SGVec2<T>& pt1, const SGVec2<T>
return !(has_neg && has_pos);
}
// 判断一个二维向量是否有NaN值
template<typename T>
inline
bool
@ -401,17 +494,20 @@ isNaN(const SGVec2<T>& v)
}
/// Output to an ostream
// 将二维向量输出到流中
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGVec2<T>& v)
{ return s << "[ " << v(0) << ", " << v(1) << " ]"; }
// 将二维双精度浮点向量转换为单精度浮点型向量
inline
SGVec2f
toVec2f(const SGVec2d& v)
{ SGVec2f f(v); return f; }
// 将二维单精度浮点向量转换为双精度浮点型向量
inline
SGVec2d
toVec2d(const SGVec2f& v)

View File

@ -13,6 +13,7 @@
#include <simgear/math/SGLimits.hxx>
#include <simgear/math/SGMisc.hxx>
//预先声明simd4_t类
template<typename T, int N> class simd4_t;
namespace simd4