diff --git a/simgear/simgear/math/SGVec2.hxx b/simgear/simgear/math/SGVec2.hxx index 3b990b4..672e3cb 100644 --- a/simgear/simgear/math/SGVec2.hxx +++ b/simgear/simgear/math/SGVec2.hxx @@ -12,13 +12,18 @@ #include /// 2D Vector Class +//SGVec2类是一个2D向量类,定义了2D向量的基本操作和运算 template 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(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(d) : simd4_t(T(0)); } + //模板构造函数,使用另一个SGVec2类型的二维向量初始化 template explicit SGVec2(const SGVec2& 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类型的常量引用,表示一个2D向量 const simd4_t &simd2(void) const { return _data; } /// Readonly raw storage interface + //返回一个simd4_t类型的引用,表示一个2D向量 simd4_t &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 SGVec2& operator*=(S s) { _data *= s; return *this; } /// Inplace scalar multiplication by 1/s + // /=运算符重载,实现向量除法 template 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类型的成员变量,表示一个2D向量 simd4_t _data; }; +// 以下是一些运算符的类外重载 /// Unary +, do nothing ... +//一元+运算符重载,什么都不做 template inline const SGVec2& @@ -115,6 +146,7 @@ operator+(const SGVec2& v) { return v; } /// Unary -, do nearly nothing +//一元-运算符重载,对向量取反[-x,-y] template inline SGVec2 @@ -122,6 +154,7 @@ operator-(SGVec2 v) { v *= -1; return v; } /// Binary + +//二元+运算符重载,实现向量加法[x1+x2,y1+y2] template inline SGVec2 @@ -129,6 +162,7 @@ operator+(SGVec2 v1, const SGVec2& v2) { v1.simd2() += v2.simd2(); return v1; } /// Binary - +//二元-运算符重载,实现向量减法[x1-x2,y1-y2] template inline SGVec2 @@ -136,6 +170,7 @@ operator-(SGVec2 v1, const SGVec2& v2) { v1.simd2() -= v2.simd2(); return v1; } /// Scalar multiplication +//标量乘法运算符重载,实现向量左数乘[s*x1,s*y1] template inline SGVec2 @@ -143,6 +178,7 @@ operator*(S s, SGVec2 v) { v.simd2() *= s; return v; } /// Scalar multiplication +//标量乘法运算符重载,实现向量右数乘[x1*s,y1*s] template inline SGVec2 @@ -152,6 +188,9 @@ operator*(SGVec2 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 inline SGVec2 @@ -159,16 +198,21 @@ mult(SGVec2 v1, const SGVec2& v2) { v1.simd2() *= v2.simd2(); return v1; } /// component wise min +//向量分量求最小值运算,实现向量分量最小值运算[min(x1,x2),min(y1,y2)] template inline SGVec2 min(SGVec2 v1, const SGVec2& v2) { v1.simd2() = simd4::min(v1.simd2(), v2.simd2()); return v1; } + +//向量分量与右侧标量求最小值运算,实现向量分量与标量最小值运算[min(x,s),min(y,s)] template inline SGVec2 min(SGVec2 v, S s) { v.simd2() = simd4::min(v.simd2(), simd4_t(s)); return v; } + +//向量分量与左侧标量求最小值运算,实现向量分量与标量最小值运算[min(s,x),min(s,y)] template inline SGVec2 @@ -176,16 +220,21 @@ min(S s, SGVec2 v) { v.sim2() = simd4::min(v.simd2(), simd4_t(s)); return v; } /// component wise max +//向量分量求最大值运算,实现向量分量最大值运算[max(x1,x2),max(y1,y2)] template inline SGVec2 max(SGVec2 v1, const SGVec2& v2) { v1.simd2() = simd4::max(v1.simd2(), v2.simd2()); return v1; } + +//向量分量与右侧标量求最大值运算,实现向量分量与标量最大值运算[max(x,s),max(y,s)] template inline SGVec2 max(const SGVec2& v, S s) { v = simd4::max(v.simd2(), simd4_t(s)); return v; } + +//向量分量与左侧标量求最大值运算,实现向量分量与标量最大值运算[max(s,x),max(s,y)] template inline SGVec2 @@ -194,6 +243,7 @@ max(S s, const SGVec2& 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 SGVec2 addClipOverflow(SGVec2 const& lhs, SGVec2 const& rhs) { @@ -204,6 +254,7 @@ SGVec2 addClipOverflow(SGVec2 const& lhs, SGVec2 const& rhs) } /// Scalar dot product +//向量点积运算,实现向量点积运算 x1*x2+y1*y2 template inline T @@ -211,6 +262,7 @@ dot(const SGVec2& v1, const SGVec2& 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 inline T @@ -219,6 +271,7 @@ norm(const SGVec2& v) /// The squared euclidean norm of the vector /// Comparing two squared values prevents two computionally heavy sqrt calls. +//向量二范数平方运算,实现向量二范数平方运算 (x^2+y^2) template inline T @@ -226,6 +279,7 @@ norm2(const SGVec2& 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 inline T @@ -234,6 +288,7 @@ length(const SGVec2& v) /// The 1-norm of the vector, this one is the fastest length function we /// can implement on modern cpu's +//向量一范数运算,实现向量一范数运算 |x|+|y| template inline T @@ -241,6 +296,7 @@ norm1(SGVec2 v) { v.simd2() = simd4::abs(v.simd2()); return (v(0)+v(1)); } /// The inf-norm of the vector +//向量无穷范数运算,实现向量无穷范数运算 max(|x|,|y|) template inline T @@ -251,6 +307,7 @@ normI(SGVec2 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 inline SGVec2 @@ -263,6 +320,7 @@ normalize(const SGVec2& v) } /// Return true if exactly the same +//向量相等判断运算符重载,实现向量相等判断 x1==x2 && y1==y2 template inline bool @@ -270,6 +328,7 @@ operator==(const SGVec2& v1, const SGVec2& v2) { return v1(0) == v2(0) && v1(1) == v2(1); } /// Return true if not exactly the same +//向量不相等判断运算符重载,实现向量不相等判断 x1!=x2 || y1!=y2 template inline bool @@ -277,6 +336,7 @@ operator!=(const SGVec2& v1, const SGVec2& v2) { return ! (v1 == v2); } /// Return true if smaller, good for putting that into a std::map +//向量小于判断运算符重载,实现向量小于判断 x1 inline bool @@ -287,6 +347,7 @@ operator<(const SGVec2& v1, const SGVec2& v2) else return (v1(1) < v2(1)); } +//向量小于等于判断运算符重载,实现向量小于等于判断 x1<=x2 || (x1==x2 && y1<=y2) template inline bool @@ -297,12 +358,14 @@ operator<=(const SGVec2& v1, const SGVec2& v2) else return (v1(1) <= v2(1)); } +//向量大于判断运算符重载,实现向量大于判断 x1>x2 || (x1==x2 && y1>y2) template inline bool operator>(const SGVec2& v1, const SGVec2& v2) { return operator<(v2, v1); } +//向量大于等于判断运算符重载,实现向量大于等于判断 x1>=x2 || (x1==x2 && y1>=y2) template inline bool @@ -310,6 +373,14 @@ operator>=(const SGVec2& v1, const SGVec2& v2) { return operator<=(v2, v1); } /// Return true if equal to the relative tolerance tol +// 判断两个二维向量是否在给定误差范围内相等, +// rtol: 相对误差容限(relative tolerance) +// atol: 绝对误差容限(absolute tolerance) +// 这种比较方式特别适用于: +// 1. 处理浮点数计算中的舍入误差 +// 2. 当向量的分量值很大时,允许有更大的绝对误差(通过相对误差项) +// 3. 当向量的分量值很小时,通过绝对误差项来避免过于严格的比较 +// 这比简单的相等比较(==)更实用,因为在计算机的浮点数运算中,由于舍入误差,很少有两个浮点数完全相等的情况。 template inline bool @@ -317,6 +388,9 @@ equivalent(const SGVec2& v1, const SGVec2& 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 inline bool @@ -324,6 +398,8 @@ equivalent(const SGVec2& v1, const SGVec2& 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 inline bool @@ -334,6 +410,7 @@ equivalent(const SGVec2& v1, const SGVec2& v2) } /// The euclidean distance of the two vectors +// 计算两个二维向量之间的欧几里得距离 sqrt((x1-x2)^2+(y1-y2)^2) template inline T @@ -341,6 +418,7 @@ dist(const SGVec2& v1, const SGVec2& v2) { return simd4::magnitude(v1.simd2() - v2.simd2()); } /// The squared euclidean distance of the two vectors +// 计算两个二维向量之间的欧几里得距离的平方 (x1-x2)^2+(y1-y2)^2 template inline T @@ -348,6 +426,9 @@ distSqr(SGVec2 v1, const SGVec2& 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::min() < denom应该有问题,为了避免除以0应该判断denom <= SGLimits::min() + template inline SGVec2 @@ -355,10 +436,12 @@ projection(const SGVec2& u, const SGVec2& d) { T denom = simd4::magnitude2(d.simd2()); T ud = dot(u, d); - if (SGLimits::min() < denom) return u; + //if (SGLimits::min() < denom) return u; + if (denom <= SGLimits::min()) return u; //这里改了一下 else return d * (dot(u, d) / denom); } +// 计算两个二维向量之间的线性插值,tau在[0,1]之间 template inline SGVec2 @@ -370,6 +453,11 @@ interpolate(T tau, const SGVec2& v1, const SGVec2& v2) } // Helper function for point_in_triangle +// 用于计算三个点构成的有向面积(signed area),它是判断点是否在三角形内的辅助函数。 +//正值:表示三个点按逆时针方向排列 +//负值:表示三个点按顺时针方向排列 +//零值:表示三点共线 + template inline T @@ -379,6 +467,10 @@ pt_determine(const SGVec2& pt1, const SGVec2& pt2, const SGVec2& pt3) } // Is testpt inside the triangle formed by the other three points? +// 判断点testpt是否在三角形内 +// 如果一个点在三角形内部,那么它与三角形任意两个顶点形成的有向面积的符号应该都相同(要么都是正的,要么都是负的) +// 如果一个点在三角形外部,那么它与三角形任意两个顶点形成的有向面积的符号应该相反(一个为正,一个为负) +// 如果一个点在三角形边上,那么它与三角形任意两个顶点形成的有向面积的符号应该为0 template inline bool @@ -392,6 +484,7 @@ point_in_triangle(const SGVec2& testpt, const SGVec2& pt1, const SGVec2 return !(has_neg && has_pos); } +// 判断一个二维向量是否有NaN值 template inline bool @@ -401,17 +494,20 @@ isNaN(const SGVec2& v) } /// Output to an ostream +// 将二维向量输出到流中 template inline std::basic_ostream& operator<<(std::basic_ostream& s, const SGVec2& v) { return s << "[ " << v(0) << ", " << v(1) << " ]"; } +// 将二维双精度浮点向量转换为单精度浮点型向量 inline SGVec2f toVec2f(const SGVec2d& v) { SGVec2f f(v); return f; } +// 将二维单精度浮点向量转换为双精度浮点型向量 inline SGVec2d toVec2d(const SGVec2f& v) diff --git a/simgear/simgear/math/simd.hxx b/simgear/simgear/math/simd.hxx index 7329379..4586f94 100644 --- a/simgear/simgear/math/simd.hxx +++ b/simgear/simgear/math/simd.hxx @@ -13,6 +13,7 @@ #include #include +//预先声明simd4_t类 template class simd4_t; namespace simd4