diff --git a/simgear/simgear/math/SGGeoc.hxx b/simgear/simgear/math/SGGeoc.hxx index 5117e8e..e549a5f 100644 --- a/simgear/simgear/math/SGGeoc.hxx +++ b/simgear/simgear/math/SGGeoc.hxx @@ -1,10 +1,13 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-FileCopyrightText: 2006 Mathias Froehlich +// SGGeoc 头文件 +// 定义了地心坐标类SGGeoc,用于表示地球上的位置 lon为经度, lat为纬度, radius为距离地球中心的距离 + #ifndef SGGeoc_H #define SGGeoc_H -#include +#include // 包含常量定义的头文件 // #define SG_GEOC_NATIVE_DEGREE @@ -12,65 +15,91 @@ class SGGeoc { public: /// Default constructor, initializes the instance to lat = lon = lat = 0 + // 默认构造函数,将实例初始化为 lat = lon = lat = 0 SGGeoc(void); /// Factory from angular values in radians and radius in ft + // 工厂方法:从弧度值和半径(单位:英尺)创建实例 static SGGeoc fromRadFt(double lon, double lat, double radius); /// Factory from angular values in degrees and radius in ft + // 工厂方法:从角度值和半径(单位:英尺)创建实例 static SGGeoc fromDegFt(double lon, double lat, double radius); /// Factory from angular values in radians and radius in m + // 工厂方法:从弧度值和半径(单位:米)创建实例 static SGGeoc fromRadM(double lon, double lat, double radius); /// Factory from angular values in degrees and radius in m + // 工厂方法:从角度值和半径(单位:米)创建实例 static SGGeoc fromDegM(double lon, double lat, double radius); /// Factory to convert position from a cartesian position assumed to be /// in wgs84 measured in meters /// Note that this conversion is relatively expensive to compute + // 工厂方法:从ECEF坐标(单位:米)创建实例, 使用WGS84坐标系, 注意这个转换耗时较长 static SGGeoc fromCart(const SGVec3& cart); /// Factory to convert position from a geodetic position /// Note that this conversion is relatively expensive to compute + // 工厂方法:从地理坐标创建实例, 注意这个转换耗时较长 static SGGeoc fromGeod(const SGGeod& geod); /// Return the geocentric longitude in radians + // 返回经度(单位:弧度) double getLongitudeRad(void) const; /// Set the geocentric longitude from the argument given in radians + // 设置经度(单位:弧度) void setLongitudeRad(double lon); /// Return the geocentric longitude in degrees + // 返回经度(单位:度) double getLongitudeDeg(void) const; /// Set the geocentric longitude from the argument given in degrees + // 设置经度(单位:度) void setLongitudeDeg(double lon); /// Return the geocentric latitude in radians + // 返回纬度(单位:弧度) double getLatitudeRad(void) const; /// Set the geocentric latitude from the argument given in radians + // 设置纬度(单位:弧度) void setLatitudeRad(double lat); /// Return the geocentric latitude in degrees + // 返回纬度(单位:度) double getLatitudeDeg(void) const; /// Set the geocentric latitude from the argument given in degrees + // 设置纬度(单位:度) void setLatitudeDeg(double lat); /// Return the geocentric radius in meters + // 返回距地心距离(单位:米) double getRadiusM(void) const; /// Set the geocentric radius from the argument given in meters + // 设置距地心距离(单位:米) void setRadiusM(double radius); /// Return the geocentric radius in feet + // 返回距地心距离(单位:英尺) double getRadiusFt(void) const; /// Set the geocentric radius from the argument given in feet + // 设置距地心距离(单位:英尺) void setRadiusFt(double radius); + /// 通过航向和距离计算一个新的地心坐标(单位:弧度), + /// 航向是相对于当前坐标的航向,距离是相对于当前坐标的距离 SGGeoc advanceRadM(double course, double distance) const; + /// 返回两个地心坐标之间的航向(单位:弧度) static double courseRad(const SGGeoc& from, const SGGeoc& to); + /// 返回两个地心坐标之间的航向(单位:度) static double courseDeg(const SGGeoc& from, const SGGeoc& to); + /// 返回两个地心坐标之间的距离(单位:米) static double distanceM(const SGGeoc& from, const SGGeoc& to); // Compare two geocentric positions for equality + // 比较两个地心坐标是否相等 bool operator == ( const SGGeoc & other ) const; private: /// This one is private since construction is not unique if you do /// not know the units of the arguments, use the factory methods for /// that purpose + // 私有构造函数,因为构造函数不是唯一的,如果不知道参数的单位,请使用工厂方法 SGGeoc(double lon, double lat, double radius); /// The actual data, angles in degree, radius in meters @@ -80,9 +109,15 @@ private: /// to other representations or compute rotation matrices. But both tasks /// are computionally intensive anyway and that additional 'toRadian' /// conversion does not hurt too much - double _lon; - double _lat; - double _radius; + /// 实际数据:角度以度为单位,半径以米为单位 + /// 选择以度为单位存储值的原因是,flightgear/terragear中的大多数代码 + /// 都使用度作为原生的输入和输出值。 + /// 使用弧度更有意义的情况是在我们进行坐标转换 + /// 或计算旋转矩阵时。但这两项任务本身计算量就很大, + /// 所以额外的"转换为弧度"操作并不会造成太大影响 + double _lon; // 经度 + double _lat; // 纬度 + double _radius; // 距地心距离 }; inline @@ -321,6 +356,7 @@ SGGeoc::operator == ( const SGGeoc & other ) const } /// Output to an ostream +// 自定义的输出流操作符,用于将SGGeoc对象输出到流中 template inline std::basic_ostream& diff --git a/simgear/simgear/math/SGGeod.hxx b/simgear/simgear/math/SGGeod.hxx index 63080ed..a3ea5f8 100644 --- a/simgear/simgear/math/SGGeod.hxx +++ b/simgear/simgear/math/SGGeod.hxx @@ -1,6 +1,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-FileCopyrightText: 2006 Mathias Froehlich +// SGGeod 头文件 +// 定义了地理坐标类SGGeod,用于表示地球上的位置 lon为经度, lat为纬度, elevation为海拔高度 + #ifndef SGGeod_H #define SGGeod_H @@ -20,72 +23,98 @@ public: This is necessary because for historical reasons, ther default constructor above initialises to zero,zero,zero which *is* */ + // 返回一个无效的SGGeod对象,用于表示无效的地理坐标 static SGGeod invalid(); /// Factory from angular values in radians and elevation is 0 + // 工厂方法:从弧度值创建实例, 海拔高度为0 static SGGeod fromRad(double lon, double lat); /// Factory from angular values in degrees and elevation is 0 + // 工厂方法:从角度值创建实例, 海拔高度为0 static SGGeod fromDeg(double lon, double lat); /// Factory from angular values in radians and elevation in ft + // 工厂方法:从弧度值和海拔高度(单位:英尺)创建实例 static SGGeod fromRadFt(double lon, double lat, double elevation); /// Factory from angular values in degrees and elevation in ft + // 工厂方法:从角度值和海拔高度(单位:英尺)创建实例 static SGGeod fromDegFt(double lon, double lat, double elevation); /// Factory from angular values in radians and elevation in m + // 工厂方法:从弧度值和海拔高度(单位:米)创建实例 static SGGeod fromRadM(double lon, double lat, double elevation); /// Factory from angular values in degrees and elevation in m + // 工厂方法:从角度值和海拔高度(单位:米)创建实例 static SGGeod fromDegM(double lon, double lat, double elevation); /// Factory from an other SGGeod and a different elevation in m + // 工厂方法:从另一个地理坐标和不同的海拔高度(单位:米)创建实例 static SGGeod fromGeodM(const SGGeod& geod, double elevation); /// Factory from an other SGGeod and a different elevation in ft + // 工厂方法:从另一个地理坐标和不同的海拔高度(单位:英尺)创建实例 static SGGeod fromGeodFt(const SGGeod& geod, double elevation); /// Factory to convert position from a cartesian position assumed to be /// in wgs84 measured in meters /// Note that this conversion is relatively expensive to compute + // 工厂方法:从ECEF坐标(单位:米)创建实例, 使用WGS84坐标系, 注意这个转换耗时较长 static SGGeod fromCart(const SGVec3& cart); /// Factory to convert position from a geocentric position /// Note that this conversion is relatively expensive to compute + // 工厂方法:从地心坐标创建实例, 注意这个转换耗时较长 static SGGeod fromGeoc(const SGGeoc& geoc); /// Return the geodetic longitude in radians + // 返回经度(单位:弧度) double getLongitudeRad(void) const; /// Set the geodetic longitude from the argument given in radians + // 设置经度(单位:弧度) void setLongitudeRad(double lon); /// Return the geodetic longitude in degrees + // 返回经度(单位:度) double getLongitudeDeg(void) const; /// Set the geodetic longitude from the argument given in degrees + // 设置经度(单位:度) void setLongitudeDeg(double lon); /// Return the geodetic latitude in radians + // 返回纬度(单位:弧度) double getLatitudeRad(void) const; /// Set the geodetic latitude from the argument given in radians + // 设置纬度(单位:弧度) void setLatitudeRad(double lat); /// Return the geodetic latitude in degrees + // 返回纬度(单位:度) double getLatitudeDeg(void) const; /// Set the geodetic latitude from the argument given in degrees + // 设置纬度(单位:度) void setLatitudeDeg(double lat); /// Return the geodetic elevation in meters + // 返回海拔高度(单位:米) double getElevationM(void) const; /// Set the geodetic elevation from the argument given in meters + // 设置海拔高度(单位:米) void setElevationM(double elevation); /// Return the geodetic elevation in feet + // 返回海拔高度(单位:英尺) double getElevationFt(void) const; /// Set the geodetic elevation from the argument given in feet + // 设置海拔高度(单位:英尺) void setElevationFt(double elevation); /// Compare two geodetic positions for equality + // 比较两个地理坐标是否相等 bool operator == ( const SGGeod & other ) const; /// check the Geod contains sane values (finite, inside appropriate /// ranges for lat/lon) + // 检查地理坐标是否包含合理的值(有限、在适当的范围内) bool isValid() const; private: /// This one is private since construction is not unique if you do /// not know the units of the arguments. Use the factory methods for /// that purpose + // 私有构造函数,因为构造函数不是唯一的,如果不知道参数的单位,请使用工厂方法 SGGeod(double lon, double lat, double elevation); //// FIXME: wrong comment! @@ -96,9 +125,15 @@ private: /// to other representations or compute rotation matrices. But both tasks /// are computationally intensive anyway and that additional 'toRadian' /// conversion does not hurt too much + // 实际数据:角度以度为单位,海拔高度以米为单位 + // 选择以度为单位存储值的原因是,flightgear/terragear中的大多数代码 + // 都使用度作为原生的输入和输出值。 + // 使用弧度更有意义的情况是在我们进行坐标转换 + /// 或计算旋转矩阵时。但这两项任务本身计算量就很大, + /// 所以额外的"转换为弧度"操作并不会造成太大影响 double _lon; double _lat; - double _elevation; + double _elevation; // 海拔高度 }; inline diff --git a/simgear/simgear/math/SGGeodesy.cxx b/simgear/simgear/math/SGGeodesy.cxx index 70d5a98..2db5321 100644 --- a/simgear/simgear/math/SGGeodesy.cxx +++ b/simgear/simgear/math/SGGeodesy.cxx @@ -5,17 +5,17 @@ #include -#include -#include -#include -#include +#include // 包含日志记录相关的头文件 +#include // 包含字符串处理相关的头文件 +#include // 包含SG相关的内联函数 +#include // 包含异常处理相关的头文件 #include "SGMath.hxx" // These are hard numbers from the WGS84 standard. DON'T MODIFY // unless you want to change the datum. -#define _EQURAD 6378137.0 -#define _FLATTENING 298.257223563 +#define _EQURAD 6378137.0 // 地球椭球体长半轴 +#define _FLATTENING 298.257223563 // 地球椭球体扁率 // These are derived quantities more useful to the code: #if 0 @@ -27,9 +27,12 @@ // precision calculator (the compiler might lose a few bits in the FPU // operations). These are specified to 81 bits of mantissa, which is // higher than any FPU known to me: -#define _SQUASH 0.9966471893352525192801545 -#define _STRETCH 1.0033640898209764189003079 -#define _POLRAD 6356752.3142451794975639668 +// 上述值的高精度版本是使用任意精度计算器生成的 +// (编译器在浮点运算中可能会丢失几位精度)。 +// 这些值指定了81位的尾数精度,这比我所知道的任何浮点运算单元(FPU)的精度都要高: +#define _SQUASH 0.9966471893352525192801545 // 地球椭球体压缩率 +#define _STRETCH 1.0033640898209764189003079 // 地球椭球体拉伸率 +#define _POLRAD 6356752.3142451794975639668 // 地球椭球体极半径 #endif // The constants from the WGS84 standard @@ -42,12 +45,12 @@ const double SGGeodesy::POLRAD = _POLRAD; // additional derived and precomputable ones // for the geodetic conversion algorithm -#define E2 fabs(1 - _SQUASH*_SQUASH) -static double a = _EQURAD; -static double ra2 = 1/(_EQURAD*_EQURAD); +#define E2 fabs(1 - _SQUASH*_SQUASH) // 地球椭球体偏心率平方 +static double a = _EQURAD; // 地球椭球体长半轴 +static double ra2 = 1/(_EQURAD*_EQURAD); // 地球椭球体长半轴平方的倒数 //static double e = sqrt(E2); -static double e2 = E2; -static double e4 = E2*E2; +static double e2 = E2; // 地球椭球体偏心率平方 +static double e4 = E2*E2; // 地球椭球体偏心率平方的平方 #undef _EQURAD #undef _FLATTENING @@ -56,7 +59,7 @@ static double e4 = E2*E2; #undef _POLRAD #undef E2 -using namespace std::string_literals; +using namespace std::string_literals; // 使用字符串字面量 void SGGeodesy::SGCartToGeod(const SGVec3& cart, SGGeod& geod) @@ -74,6 +77,10 @@ SGGeodesy::SGCartToGeod(const SGVec3& cart, SGGeod& geod) // Define the innermost sphere of small radius as earth center and return the // coordinates 0/0/-EQURAD. It may be any other place on geoide's surface, // the Northpole, Hawaii or Wentorf. This one was easy to code ;-) + // 这个函数在地球中心区域失败,所以在这里捕获这个特殊情况。 + // 定义最内层的球体为地球中心,并返回坐标0/0/-EQURAD。 + // 它可以是地球表面上的任何其他地方, + // 北极、夏威夷或文托夫。这个很简单。 geod.setLongitudeRad( 0.0 ); geod.setLatitudeRad( 0.0 ); geod.setElevationM( -EQURAD ); @@ -90,6 +97,11 @@ SGGeodesy::SGCartToGeod(const SGVec3& cart, SGGeod& geod) slightly negative values for s due to floating point rounding errors cause nan for sqrt(s*(2+s)) We can probably clamp the resulting parable to positive numbers +*/ +/* + 对于s=[-2..0],s*(2+s) 是负数, + 由于浮点运算误差,s的稍微负值会导致sqrt(s*(2+s))出现nan + 我们可以将结果的抛物线限制为正数 */ if( s >= -2.0 && s <= 0.0 ) s = 0.0; @@ -130,6 +142,8 @@ SGGeodesy::SGGeodToSeaLevelRadius(const SGGeod& geod) { // this is just a simplified version of the SGGeodToCart function above, // substitute h = 0, take the 2-norm of the cartesian vector and simplify + // 这是一个简化的SGGeodToCart函数的版本, + // 将h=0代入,取笛卡尔向量的2-范数并简化 double phi = geod.getLatitudeRad(); double sphi = sin(phi); double sphi2 = sphi*sphi; @@ -171,19 +185,25 @@ SGGeodesy::SGGeocToCart(const SGGeoc& geoc, SGVec3& cart) // The XYZ/cartesian coordinate system in use puts the X axis through // zero lat/lon (off west Africa), the Z axis through the north pole, // and the Y axis through 90 degrees longitude (in the Indian Ocean). +// 使用XYZ/笛卡尔坐标系,X轴通过0/0(位于西非),Z轴通过北极,Y轴通过90度经度(在印度洋)。 // // All latitude and longitude values are in radians. Altitude is in // meters, with zero on the WGS84 ellipsoid. +// 所有纬度和经度值都是以弧度为单位。 +// 高度是以米为单位,零点在WGS84椭球体上。 // // The code below makes use of the notion of "squashed" space. This // is a 2D cylindrical coordinate system where the radius from the Z // axis is multiplied by SQUASH; the earth in this space is a perfect // circle with a radius of POLRAD. +// 下面的代码使用“压缩”空间的观念。 +// 这是一个2D圆柱坐标系,其中Z轴的半径乘以SQUASH; +// 在这个空间中,地球是一个完美的圆,半径为POLRAD。 //////////////////////////////////////////////////////////////////////// // // Direct and inverse distance functions -// +// 直接和反向距离函数 // Proceedings of the 7th International Symposium on Geodetic // Computations, 1985 // @@ -204,6 +224,7 @@ static inline double M0( double e2 ) { // given, lat1, lon1, az1 and distance (s), calculate lat2, lon2 // and az2. Lat, lon, and azimuth are in degrees. distance in meters +// 给定起始点经纬度和方位角以及距离,计算目标点经纬度和方位角 static int _geo_direct_wgs_84 ( double lat1, double lon1, double az1, double s, double *lat2, double *lon2, double *az2 ) diff --git a/simgear/simgear/math/SGGeodesy.hxx b/simgear/simgear/math/SGGeodesy.hxx index 0633046..1eb14b3 100644 --- a/simgear/simgear/math/SGGeodesy.hxx +++ b/simgear/simgear/math/SGGeodesy.hxx @@ -1,70 +1,95 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-FileCopyrightText: 2006 Mathias Froehlich +// SGGeodesy 头文件 +// 包含了一系列地理计算相关的函数,包括地球参数、坐标转换、距离计算等 + #ifndef SGGeodesy_H #define SGGeodesy_H class SGGeodesy { public: // Hard numbers from the WGS84 standard. - static const double EQURAD; - static const double iFLATTENING; - static const double SQUASH; - static const double STRETCH; - static const double POLRAD; + static const double EQURAD; // 地球赤道半径 + static const double iFLATTENING; // 地球扁率 + static const double SQUASH; // 地球压缩率 + static const double STRETCH; // 地球拉伸率 + static const double POLRAD; // 地球极半径 /// Takes a cartesian coordinate data and returns the geodetic /// coordinates. - static void SGCartToGeod(const SGVec3& cart, SGGeod& geod); + // 将ECEF坐标转换为地理坐标 + static void SGCartToGeod(const SGVec3& cart, SGGeod& geod); /// Takes a geodetic coordinate data and returns the cartesian /// coordinates. - static void SGGeodToCart(const SGGeod& geod, SGVec3& cart); + // 将地理坐标转换为ECEF坐标 + static void SGGeodToCart(const SGGeod& geod, SGVec3& cart); /// Takes a geodetic coordinate data and returns the sea level radius. - static double SGGeodToSeaLevelRadius(const SGGeod& geod); + // 根据地理坐标计算此处海平面的地球半径 + static double SGGeodToSeaLevelRadius(const SGGeod& geod); /// Takes a cartesian coordinate data and returns the geocentric /// coordinates. - static void SGCartToGeoc(const SGVec3& cart, SGGeoc& geoc); + // 将ECEF坐标转换为地心坐标 + static void SGCartToGeoc(const SGVec3& cart, SGGeoc& geoc); /// Takes a geocentric coordinate data and returns the cartesian /// coordinates. - static void SGGeocToCart(const SGGeoc& geoc, SGVec3& cart); + // 将地心坐标转换为ECEF坐标 + static void SGGeocToCart(const SGGeoc& geoc, SGVec3& cart); // Geodetic course/distance computation + // 给定起始点地理坐标和方位角以及距离,计算目标点经纬度和目标点看起始点的方位角 static bool direct(const SGGeod& p1, double course1, double distance, SGGeod& p2, double& course2); /// overloaded version of above, returns new value directly, throws /// an sg_exception on failure. + // 给定起始点地理坐标和方位角以及距离,计算目标点地理坐标 static SGGeod direct(const SGGeod& p1, double course1, double distance); + // 给定起始点和目标点地理坐标,计算起始点看目标点的方位角和目标点看起始点的方位角以及距离 static bool inverse(const SGGeod& p1, const SGGeod& p2, double& course1, double& course2, double& distance); + // 给定起始点和目标点地理坐标,计算起始点看目标点的方位角 static double courseDeg(const SGGeod& from, const SGGeod& to); + + // 给定起始点和目标点地理坐标,计算起始点和目标点之间的距离(单位:米) static double distanceM(const SGGeod& from, const SGGeod& to); + + // 给定起始点和目标点地理坐标,计算起始点和目标点之间的距离(单位:海里) static double distanceNm(const SGGeod& from, const SGGeod& to); // Geocentric course/distance computation + // 给定起始点地心坐标和方位角(单位:弧度)以及距离(单位:米),计算目标点地心坐标 static void advanceRadM(const SGGeoc& geoc, double course, double distance, SGGeoc& result); + // 给定起始点地心坐标和方位角(单位:度)以及距离(单位:米),计算目标点地心坐标 static SGGeoc advanceDegM(const SGGeoc &geoc, double course, double distance); + // 给定起始点和目标点地心坐标,计算起始点和目标点之间的方位角(单位:弧度) static double courseRad(const SGGeoc& from, const SGGeoc& to); + + // 给定起始点和目标点地心坐标,计算起始点和目标点之间的距离(单位:弧度) static double distanceRad(const SGGeoc& from, const SGGeoc& to); + + // 给定起始点和目标点地心坐标,计算起始点和目标点之间的距离(单位:米) static double distanceM(const SGGeoc& from, const SGGeoc& to); /** * compute the intersection of two (true) radials (in degrees), or return false * if no intersection culd be computed. */ + // 给定两个点地心坐标和方位角,计算两个方向向量之间的交点 static bool radialIntersection(const SGGeoc& a, double aRadial, const SGGeoc& b, double bRadial, SGGeoc& result); - + + // 给定两个点地理坐标和方位角,计算两个方向向量之间的交点 static bool radialIntersection(const SGGeod& a, double aRadial, const SGGeod& b, double bRadial, SGGeod& result); }; diff --git a/simgear/simgear/math/SGMath.hxx b/simgear/simgear/math/SGMath.hxx index 732f3f1..a86fe0a 100644 --- a/simgear/simgear/math/SGMath.hxx +++ b/simgear/simgear/math/SGMath.hxx @@ -1,6 +1,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-FileCopyrightText: 2006 Mathias Froehlich +// SGMath 头文件 +// 包含了一系列数学相关的头文件 + #ifndef SGMath_H #define SGMath_H @@ -10,13 +13,13 @@ #include "SGMathFwd.hxx" -#include "SGCMath.hxx" -#include "SGLimits.hxx" -#include "SGMisc.hxx" -#include "SGGeodesy.hxx" -#include "SGVec2.hxx" -#include "SGVec3.hxx" -#include "SGVec4.hxx" +#include "SGCMath.hxx" // 引入了std标准数学库 +#include "SGLimits.hxx" // 引入了std标准库的limits头文件,定义了用于SG的limits类 +#include "SGMisc.hxx" // 提供了一系列数学计算函数,包括最大值、最小值、无溢出加法、渐进、幂运算、归一化、四舍五入等 +#include "SGGeodesy.hxx" // 包含了一系列地理计算相关的函数,包括地球参数、坐标转换、距离计算等 +#include "SGVec2.hxx" // 定义了2D向量类SGVec2,提供了向量运算、点积、叉积等操作 +#include "SGVec3.hxx" // 定义了3D向量类SGVec3,提供了向量运算、点积、叉积等操作 +#include "SGVec4.hxx" // 定义了4D向量类SGVec4,提供了向量运算、点积、叉积等操作 #include "SGGeoc.hxx" #include "SGGeod.hxx" #include "SGQuat.hxx" diff --git a/simgear/simgear/math/SGMisc.hxx b/simgear/simgear/math/SGMisc.hxx index e3ba04c..bf7a2fd 100644 --- a/simgear/simgear/math/SGMisc.hxx +++ b/simgear/simgear/math/SGMisc.hxx @@ -1,6 +1,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-FileCopyrightText: 2006 Mathias Froehlich +// 数学工具类 +// 提供了一系列数学计算函数,包括最大值、最小值、无溢出加法、渐进、幂运算、归一化、四舍五入等 + #ifndef SGMisc_H #define SGMisc_H @@ -26,11 +29,15 @@ public: { return max(max(max(a, b), c), d); } // clip the value of a to be in the range between and including _min and _max + // 如果a小于_min,则返回_min,如果a大于_max,则返回_max,否则返回a static T clip(const T& a, const T& _min, const T& _max) { return max(_min, min(_max, a)); } /// Add two (integer) values taking care of overflows. + // 无溢出加法 + // 如果b大于0,则检查a+b是否溢出,如果溢出则返回SGLimits::max(),否则返回a+b + // 如果b小于0,则检查a+b是否溢出,如果溢出则返回SGLimits::min(),否则返回a+b static T addClipOverflow(T a, T b) { if( b > 0 ) @@ -48,6 +55,7 @@ public: } /// Add two (integer) values in place, taking care of overflows. + // 无溢出原位置加法 static T& addClipOverflowInplace(T& a, T b) { return a = addClipOverflow(a, b); @@ -61,6 +69,7 @@ public: * @param rate Max. change rate/sec * @param dt Time step (sec) */ + // 渐进: var 将以指定的速率 rate 按时间 dt 的递增向 target 渐进。 template static T seek(Var& var, T target, T rate, T dt) { @@ -76,6 +85,7 @@ public: * @tparam N Exponent * @param base Base */ + // 幂运算 template static T pow(T base) { @@ -101,7 +111,8 @@ public: static T deg2rad(const T& val) { return val*pi()/180; } - // normalize the value to be in a range between [min, max[ + // normalize the value to be in a range between [min, max] + // 归一化周期值:将 value 归一化到 [min, max] 周期范围内 static T normalizePeriodic(const T& min, const T& max, const T& value) { @@ -117,22 +128,28 @@ public: return normalized; } - // normalize the angle to be in a range between [-pi, pi[ + // normalize the angle to be in a range between [-pi, pi] + // 归一化角度:将 angle 归一化到 [-pi, pi] 范围内 static T normalizeAngle(const T& angle) { return normalizePeriodic(-pi(), pi(), angle); } - // normalize the angle to be in a range between [0, 2pi[ + // normalize the angle to be in a range between [0, 2pi] + // 归一化角度:将 angle 归一化到 [0, 2pi] 范围内 static T normalizeAngle2(const T& angle) { return normalizePeriodic(0, twopi(), angle); } + // 四舍五入:将 v 四舍五入到最接近的整数,返回结果为 T 类型 static T round(const T& v) { return floor(v + T(0.5)); } + + // 将 v 四舍五入到最接近的整数 static int roundToInt(const T& v) { return int(round(v)); } // Linear interpolation between two arbitrary typed values + // 线性插值:在 val0 和 val1 之间进行线性插值,t 是插值因子,取值范围为 [0, 1] template static S lerp(const S& val0, const S& val1, const T& t) { return val0*(T(1) - t) + val1*t; } @@ -144,9 +161,11 @@ public: return std::isnan(v); } + // 判断两个值是否相等 static bool eq(const T& a, const T& b, const T& epsilon = SGLimits::epsilon()) { return std::abs(a - b) < epsilon; } + // 判断两个值是否不相等 static bool neq(const T& a, const T& b, const T& epsilon = SGLimits::epsilon()) { return !eq(a, b, epsilon); } }; diff --git a/simgear/simgear/math/simd.hxx b/simgear/simgear/math/simd.hxx index 87936a9..7329379 100644 --- a/simgear/simgear/math/simd.hxx +++ b/simgear/simgear/math/simd.hxx @@ -1,6 +1,7 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-FileCopyrightText: 2016-2017 Erik Hofman +// sim4d,一个向量类,支持4个或更少元素的向量,主要是实现向量的运算优化 #pragma once #include @@ -17,6 +18,7 @@ template class simd4_t; namespace simd4 { +// min函数,返回两个向量中各分量的最小值 template inline simd4_t min(simd4_t v1, const simd4_t& v2) { for (int i=0; i min(simd4_t v1, const simd4_t& v2) { return v1; } +// max函数,返回两个向量中各分量的最大值 template inline simd4_t max(simd4_t v1, const simd4_t& v2) { for (int i=0; i max(simd4_t v1, const simd4_t& v2) { return v1; } +// abs函数,返回向量中各分量的绝对值 template inline simd4_t abs(simd4_t v) { for (int i=0; i abs(simd4_t v) { return v; } +// magnitude2函数,返回向量中各分量的平方和,即二范数的平方 template inline T magnitude2(const simd4_t& vi) { simd4_t v(vi); @@ -52,16 +57,19 @@ inline T magnitude2(const simd4_t& vi) { return mag2; } +// interpolate函数,返回两个向量之间的线性插值 template inline simd4_t interpolate(T tau, const simd4_t& v1, const simd4_t& v2) { return v1 + tau*(v2-v1); } +// magnitude函数,返回向量的二范数 template inline T magnitude(const simd4_t& v) { return std::sqrt(magnitude2(v)); } +// normalize函数,归一化向量 template inline T normalize(simd4_t& v) { T mag = simd4::magnitude(v); @@ -73,6 +81,7 @@ inline T normalize(simd4_t& v) { return mag; } +// dot函数,返回两个向量的点积 template inline T dot(const simd4_t& v1, const simd4_t& v2) { simd4_t v(v1*v2); @@ -83,6 +92,7 @@ inline T dot(const simd4_t& v1, const simd4_t& v2) { return dp; } +// cross函数,返回两个向量的叉积,仅三维向量有效 template inline simd4_t cross(const simd4_t& v1, const simd4_t& v2) { @@ -95,45 +105,55 @@ inline simd4_t cross(const simd4_t& v1, const simd4_t& v2) } /* namespace simd4 */ - +// simd4_t类,支持4个或更少元素的向量,主要是实现向量的运算优化 template class simd4_t final { private: +// 联合体,用于存储4个元素的向量或N个元素的向量(N<=4) union { T _v4[4]; T vec[N]; }; public: +// 构造函数,初始化为全0 simd4_t(void) { for (int i=0; i<4; ++i) _v4[i] = 0; } +// 构造函数,初始化为一个标量 simd4_t(T s) { for (int i=0; i simd4_t(const simd4_t& v) { std::memcpy(_v4, v.ptr(), sizeof(T[M])); for (int i=(M inline simd4_t& operator=(const simd4_t& v) { *this = simd4_t(v); return *this; } - +// +=运算符重载,将一个标量加到N维向量的每个元素上 inline simd4_t& operator+=(T s) { for (int i=0; i& operator+=(const T v[N]) { for (int i=0; i& operator+=(const simd4_t& v) { for (int i=0; i& operator-=(T s) { for (int i=0; i& operator-=(const T v[N]) { for (int i=0; i& operator-=(const simd4_t& v) { for (int i=0; i& operator*=(T s) { for (int i=0; i& operator*=(const T v[N]) { for (int i=0; i& operator*=(const simd4_t& v) { for (int i=0; i& operator/=(T s) { for (int i=0; i& operator/=(const T v[N]) { for (int i=0; i& operator/=(const simd4_t& v) { for (int i=0; i inline simd4_t operator-(const simd4_t& v) { simd4_t r(T(0)); @@ -245,36 +276,42 @@ inline simd4_t operator-(const simd4_t& v) { return r; } +// +运算符重载,返回两个N维向量的和 template inline simd4_t operator+(simd4_t v1, const simd4_t& v2) { v1 += v2; return v1; } +// -运算符重载,返回两个N维向量的差 template inline simd4_t operator-(simd4_t v1, const simd4_t& v2) { v1 -= v2; return v1; } +// *运算符重载,将一个N维向量乘以一个N维向量(对应元素相乘) template inline simd4_t operator*(simd4_t v1, const simd4_t& v2) { v1 *= v2; return v1; } +// /运算符重载,将一个N维向量除以一个N维向量(对应元素相除) template inline simd4_t operator/(simd4_t v1, const simd4_t& v2) { v1 /= v2; return v1; } +// *运算符重载,将一个标量乘以一个N维向量 template inline simd4_t operator*(T f, simd4_t v) { v *= f; return v; } +// *运算符重载,将一个N维向量乘以一个标量 template inline simd4_t operator*(simd4_t v, T f) { v *= f;