This commit is contained in:
zd383321154 2025-05-26 23:27:31 +08:00
parent 6ead17de2f
commit c8b1414fca
7 changed files with 228 additions and 52 deletions

View File

@ -1,10 +1,13 @@
// SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de> // SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de>
// SGGeoc 头文件
// 定义了地心坐标类SGGeoc用于表示地球上的位置 lon为经度, lat为纬度, radius为距离地球中心的距离
#ifndef SGGeoc_H #ifndef SGGeoc_H
#define SGGeoc_H #define SGGeoc_H
#include <simgear/constants.h> #include <simgear/constants.h> // 包含常量定义的头文件
// #define SG_GEOC_NATIVE_DEGREE // #define SG_GEOC_NATIVE_DEGREE
@ -12,65 +15,91 @@
class SGGeoc { class SGGeoc {
public: public:
/// Default constructor, initializes the instance to lat = lon = lat = 0 /// Default constructor, initializes the instance to lat = lon = lat = 0
// 默认构造函数,将实例初始化为 lat = lon = lat = 0
SGGeoc(void); SGGeoc(void);
/// Factory from angular values in radians and radius in ft /// Factory from angular values in radians and radius in ft
// 工厂方法:从弧度值和半径(单位:英尺)创建实例
static SGGeoc fromRadFt(double lon, double lat, double radius); static SGGeoc fromRadFt(double lon, double lat, double radius);
/// Factory from angular values in degrees and radius in ft /// Factory from angular values in degrees and radius in ft
// 工厂方法:从角度值和半径(单位:英尺)创建实例
static SGGeoc fromDegFt(double lon, double lat, double radius); static SGGeoc fromDegFt(double lon, double lat, double radius);
/// Factory from angular values in radians and radius in m /// Factory from angular values in radians and radius in m
// 工厂方法:从弧度值和半径(单位:米)创建实例
static SGGeoc fromRadM(double lon, double lat, double radius); static SGGeoc fromRadM(double lon, double lat, double radius);
/// Factory from angular values in degrees and radius in m /// Factory from angular values in degrees and radius in m
// 工厂方法:从角度值和半径(单位:米)创建实例
static SGGeoc fromDegM(double lon, double lat, double radius); static SGGeoc fromDegM(double lon, double lat, double radius);
/// Factory to convert position from a cartesian position assumed to be /// Factory to convert position from a cartesian position assumed to be
/// in wgs84 measured in meters /// in wgs84 measured in meters
/// Note that this conversion is relatively expensive to compute /// Note that this conversion is relatively expensive to compute
// 工厂方法从ECEF坐标单位创建实例, 使用WGS84坐标系, 注意这个转换耗时较长
static SGGeoc fromCart(const SGVec3<double>& cart); static SGGeoc fromCart(const SGVec3<double>& cart);
/// Factory to convert position from a geodetic position /// Factory to convert position from a geodetic position
/// Note that this conversion is relatively expensive to compute /// Note that this conversion is relatively expensive to compute
// 工厂方法:从地理坐标创建实例, 注意这个转换耗时较长
static SGGeoc fromGeod(const SGGeod& geod); static SGGeoc fromGeod(const SGGeod& geod);
/// Return the geocentric longitude in radians /// Return the geocentric longitude in radians
// 返回经度(单位:弧度)
double getLongitudeRad(void) const; double getLongitudeRad(void) const;
/// Set the geocentric longitude from the argument given in radians /// Set the geocentric longitude from the argument given in radians
// 设置经度(单位:弧度)
void setLongitudeRad(double lon); void setLongitudeRad(double lon);
/// Return the geocentric longitude in degrees /// Return the geocentric longitude in degrees
// 返回经度(单位:度)
double getLongitudeDeg(void) const; double getLongitudeDeg(void) const;
/// Set the geocentric longitude from the argument given in degrees /// Set the geocentric longitude from the argument given in degrees
// 设置经度(单位:度)
void setLongitudeDeg(double lon); void setLongitudeDeg(double lon);
/// Return the geocentric latitude in radians /// Return the geocentric latitude in radians
// 返回纬度(单位:弧度)
double getLatitudeRad(void) const; double getLatitudeRad(void) const;
/// Set the geocentric latitude from the argument given in radians /// Set the geocentric latitude from the argument given in radians
// 设置纬度(单位:弧度)
void setLatitudeRad(double lat); void setLatitudeRad(double lat);
/// Return the geocentric latitude in degrees /// Return the geocentric latitude in degrees
// 返回纬度(单位:度)
double getLatitudeDeg(void) const; double getLatitudeDeg(void) const;
/// Set the geocentric latitude from the argument given in degrees /// Set the geocentric latitude from the argument given in degrees
// 设置纬度(单位:度)
void setLatitudeDeg(double lat); void setLatitudeDeg(double lat);
/// Return the geocentric radius in meters /// Return the geocentric radius in meters
// 返回距地心距离(单位:米)
double getRadiusM(void) const; double getRadiusM(void) const;
/// Set the geocentric radius from the argument given in meters /// Set the geocentric radius from the argument given in meters
// 设置距地心距离(单位:米)
void setRadiusM(double radius); void setRadiusM(double radius);
/// Return the geocentric radius in feet /// Return the geocentric radius in feet
// 返回距地心距离(单位:英尺)
double getRadiusFt(void) const; double getRadiusFt(void) const;
/// Set the geocentric radius from the argument given in feet /// Set the geocentric radius from the argument given in feet
// 设置距地心距离(单位:英尺)
void setRadiusFt(double radius); void setRadiusFt(double radius);
/// 通过航向和距离计算一个新的地心坐标(单位:弧度),
/// 航向是相对于当前坐标的航向,距离是相对于当前坐标的距离
SGGeoc advanceRadM(double course, double distance) const; SGGeoc advanceRadM(double course, double distance) const;
/// 返回两个地心坐标之间的航向(单位:弧度)
static double courseRad(const SGGeoc& from, const SGGeoc& to); static double courseRad(const SGGeoc& from, const SGGeoc& to);
/// 返回两个地心坐标之间的航向(单位:度)
static double courseDeg(const SGGeoc& from, const SGGeoc& to); static double courseDeg(const SGGeoc& from, const SGGeoc& to);
/// 返回两个地心坐标之间的距离(单位:米)
static double distanceM(const SGGeoc& from, const SGGeoc& to); static double distanceM(const SGGeoc& from, const SGGeoc& to);
// Compare two geocentric positions for equality // Compare two geocentric positions for equality
// 比较两个地心坐标是否相等
bool operator == ( const SGGeoc & other ) const; bool operator == ( const SGGeoc & other ) const;
private: private:
/// This one is private since construction is not unique if you do /// This one is private since construction is not unique if you do
/// not know the units of the arguments, use the factory methods for /// not know the units of the arguments, use the factory methods for
/// that purpose /// that purpose
// 私有构造函数,因为构造函数不是唯一的,如果不知道参数的单位,请使用工厂方法
SGGeoc(double lon, double lat, double radius); SGGeoc(double lon, double lat, double radius);
/// The actual data, angles in degree, radius in meters /// The actual data, angles in degree, radius in meters
@ -80,9 +109,15 @@ private:
/// to other representations or compute rotation matrices. But both tasks /// to other representations or compute rotation matrices. But both tasks
/// are computionally intensive anyway and that additional 'toRadian' /// are computionally intensive anyway and that additional 'toRadian'
/// conversion does not hurt too much /// conversion does not hurt too much
double _lon; /// 实际数据:角度以度为单位,半径以米为单位
double _lat; /// 选择以度为单位存储值的原因是flightgear/terragear中的大多数代码
double _radius; /// 都使用度作为原生的输入和输出值。
/// 使用弧度更有意义的情况是在我们进行坐标转换
/// 或计算旋转矩阵时。但这两项任务本身计算量就很大,
/// 所以额外的"转换为弧度"操作并不会造成太大影响
double _lon; // 经度
double _lat; // 纬度
double _radius; // 距地心距离
}; };
inline inline
@ -321,6 +356,7 @@ SGGeoc::operator == ( const SGGeoc & other ) const
} }
/// Output to an ostream /// Output to an ostream
// 自定义的输出流操作符用于将SGGeoc对象输出到流中
template<typename char_type, typename traits_type> template<typename char_type, typename traits_type>
inline inline
std::basic_ostream<char_type, traits_type>& std::basic_ostream<char_type, traits_type>&

View File

@ -1,6 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de> // SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de>
// SGGeod 头文件
// 定义了地理坐标类SGGeod用于表示地球上的位置 lon为经度, lat为纬度, elevation为海拔高度
#ifndef SGGeod_H #ifndef SGGeod_H
#define 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 This is necessary because for historical reasons, ther default constructor above initialises to zero,zero,zero
which *is* which *is*
*/ */
// 返回一个无效的SGGeod对象用于表示无效的地理坐标
static SGGeod invalid(); static SGGeod invalid();
/// Factory from angular values in radians and elevation is 0 /// Factory from angular values in radians and elevation is 0
// 工厂方法:从弧度值创建实例, 海拔高度为0
static SGGeod fromRad(double lon, double lat); static SGGeod fromRad(double lon, double lat);
/// Factory from angular values in degrees and elevation is 0 /// Factory from angular values in degrees and elevation is 0
// 工厂方法:从角度值创建实例, 海拔高度为0
static SGGeod fromDeg(double lon, double lat); static SGGeod fromDeg(double lon, double lat);
/// Factory from angular values in radians and elevation in ft /// Factory from angular values in radians and elevation in ft
// 工厂方法:从弧度值和海拔高度(单位:英尺)创建实例
static SGGeod fromRadFt(double lon, double lat, double elevation); static SGGeod fromRadFt(double lon, double lat, double elevation);
/// Factory from angular values in degrees and elevation in ft /// Factory from angular values in degrees and elevation in ft
// 工厂方法:从角度值和海拔高度(单位:英尺)创建实例
static SGGeod fromDegFt(double lon, double lat, double elevation); static SGGeod fromDegFt(double lon, double lat, double elevation);
/// Factory from angular values in radians and elevation in m /// Factory from angular values in radians and elevation in m
// 工厂方法:从弧度值和海拔高度(单位:米)创建实例
static SGGeod fromRadM(double lon, double lat, double elevation); static SGGeod fromRadM(double lon, double lat, double elevation);
/// Factory from angular values in degrees and elevation in m /// Factory from angular values in degrees and elevation in m
// 工厂方法:从角度值和海拔高度(单位:米)创建实例
static SGGeod fromDegM(double lon, double lat, double elevation); static SGGeod fromDegM(double lon, double lat, double elevation);
/// Factory from an other SGGeod and a different elevation in m /// Factory from an other SGGeod and a different elevation in m
// 工厂方法:从另一个地理坐标和不同的海拔高度(单位:米)创建实例
static SGGeod fromGeodM(const SGGeod& geod, double elevation); static SGGeod fromGeodM(const SGGeod& geod, double elevation);
/// Factory from an other SGGeod and a different elevation in ft /// Factory from an other SGGeod and a different elevation in ft
// 工厂方法:从另一个地理坐标和不同的海拔高度(单位:英尺)创建实例
static SGGeod fromGeodFt(const SGGeod& geod, double elevation); static SGGeod fromGeodFt(const SGGeod& geod, double elevation);
/// Factory to convert position from a cartesian position assumed to be /// Factory to convert position from a cartesian position assumed to be
/// in wgs84 measured in meters /// in wgs84 measured in meters
/// Note that this conversion is relatively expensive to compute /// Note that this conversion is relatively expensive to compute
// 工厂方法从ECEF坐标单位创建实例, 使用WGS84坐标系, 注意这个转换耗时较长
static SGGeod fromCart(const SGVec3<double>& cart); static SGGeod fromCart(const SGVec3<double>& cart);
/// Factory to convert position from a geocentric position /// Factory to convert position from a geocentric position
/// Note that this conversion is relatively expensive to compute /// Note that this conversion is relatively expensive to compute
// 工厂方法:从地心坐标创建实例, 注意这个转换耗时较长
static SGGeod fromGeoc(const SGGeoc& geoc); static SGGeod fromGeoc(const SGGeoc& geoc);
/// Return the geodetic longitude in radians /// Return the geodetic longitude in radians
// 返回经度(单位:弧度)
double getLongitudeRad(void) const; double getLongitudeRad(void) const;
/// Set the geodetic longitude from the argument given in radians /// Set the geodetic longitude from the argument given in radians
// 设置经度(单位:弧度)
void setLongitudeRad(double lon); void setLongitudeRad(double lon);
/// Return the geodetic longitude in degrees /// Return the geodetic longitude in degrees
// 返回经度(单位:度)
double getLongitudeDeg(void) const; double getLongitudeDeg(void) const;
/// Set the geodetic longitude from the argument given in degrees /// Set the geodetic longitude from the argument given in degrees
// 设置经度(单位:度)
void setLongitudeDeg(double lon); void setLongitudeDeg(double lon);
/// Return the geodetic latitude in radians /// Return the geodetic latitude in radians
// 返回纬度(单位:弧度)
double getLatitudeRad(void) const; double getLatitudeRad(void) const;
/// Set the geodetic latitude from the argument given in radians /// Set the geodetic latitude from the argument given in radians
// 设置纬度(单位:弧度)
void setLatitudeRad(double lat); void setLatitudeRad(double lat);
/// Return the geodetic latitude in degrees /// Return the geodetic latitude in degrees
// 返回纬度(单位:度)
double getLatitudeDeg(void) const; double getLatitudeDeg(void) const;
/// Set the geodetic latitude from the argument given in degrees /// Set the geodetic latitude from the argument given in degrees
// 设置纬度(单位:度)
void setLatitudeDeg(double lat); void setLatitudeDeg(double lat);
/// Return the geodetic elevation in meters /// Return the geodetic elevation in meters
// 返回海拔高度(单位:米)
double getElevationM(void) const; double getElevationM(void) const;
/// Set the geodetic elevation from the argument given in meters /// Set the geodetic elevation from the argument given in meters
// 设置海拔高度(单位:米)
void setElevationM(double elevation); void setElevationM(double elevation);
/// Return the geodetic elevation in feet /// Return the geodetic elevation in feet
// 返回海拔高度(单位:英尺)
double getElevationFt(void) const; double getElevationFt(void) const;
/// Set the geodetic elevation from the argument given in feet /// Set the geodetic elevation from the argument given in feet
// 设置海拔高度(单位:英尺)
void setElevationFt(double elevation); void setElevationFt(double elevation);
/// Compare two geodetic positions for equality /// Compare two geodetic positions for equality
// 比较两个地理坐标是否相等
bool operator == ( const SGGeod & other ) const; bool operator == ( const SGGeod & other ) const;
/// check the Geod contains sane values (finite, inside appropriate /// check the Geod contains sane values (finite, inside appropriate
/// ranges for lat/lon) /// ranges for lat/lon)
// 检查地理坐标是否包含合理的值(有限、在适当的范围内)
bool isValid() const; bool isValid() const;
private: private:
/// This one is private since construction is not unique if you do /// This one is private since construction is not unique if you do
/// not know the units of the arguments. Use the factory methods for /// not know the units of the arguments. Use the factory methods for
/// that purpose /// that purpose
// 私有构造函数,因为构造函数不是唯一的,如果不知道参数的单位,请使用工厂方法
SGGeod(double lon, double lat, double elevation); SGGeod(double lon, double lat, double elevation);
//// FIXME: wrong comment! //// FIXME: wrong comment!
@ -96,9 +125,15 @@ private:
/// to other representations or compute rotation matrices. But both tasks /// to other representations or compute rotation matrices. But both tasks
/// are computationally intensive anyway and that additional 'toRadian' /// are computationally intensive anyway and that additional 'toRadian'
/// conversion does not hurt too much /// conversion does not hurt too much
// 实际数据:角度以度为单位,海拔高度以米为单位
// 选择以度为单位存储值的原因是flightgear/terragear中的大多数代码
// 都使用度作为原生的输入和输出值。
// 使用弧度更有意义的情况是在我们进行坐标转换
/// 或计算旋转矩阵时。但这两项任务本身计算量就很大,
/// 所以额外的"转换为弧度"操作并不会造成太大影响
double _lon; double _lon;
double _lat; double _lat;
double _elevation; double _elevation; // 海拔高度
}; };
inline inline

View File

@ -5,17 +5,17 @@
#include <cmath> #include <cmath>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx> // 包含日志记录相关的头文件
#include <simgear/misc/strutils.hxx> #include <simgear/misc/strutils.hxx> // 包含字符串处理相关的头文件
#include <simgear/sg_inlines.h> #include <simgear/sg_inlines.h> // 包含SG相关的内联函数
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx> // 包含异常处理相关的头文件
#include "SGMath.hxx" #include "SGMath.hxx"
// These are hard numbers from the WGS84 standard. DON'T MODIFY // These are hard numbers from the WGS84 standard. DON'T MODIFY
// unless you want to change the datum. // unless you want to change the datum.
#define _EQURAD 6378137.0 #define _EQURAD 6378137.0 // 地球椭球体长半轴
#define _FLATTENING 298.257223563 #define _FLATTENING 298.257223563 // 地球椭球体扁率
// These are derived quantities more useful to the code: // These are derived quantities more useful to the code:
#if 0 #if 0
@ -27,9 +27,12 @@
// precision calculator (the compiler might lose a few bits in the FPU // precision calculator (the compiler might lose a few bits in the FPU
// operations). These are specified to 81 bits of mantissa, which is // operations). These are specified to 81 bits of mantissa, which is
// higher than any FPU known to me: // 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 #endif
// The constants from the WGS84 standard // The constants from the WGS84 standard
@ -42,12 +45,12 @@ const double SGGeodesy::POLRAD = _POLRAD;
// additional derived and precomputable ones // additional derived and precomputable ones
// for the geodetic conversion algorithm // for the geodetic conversion algorithm
#define E2 fabs(1 - _SQUASH*_SQUASH) #define E2 fabs(1 - _SQUASH*_SQUASH) // 地球椭球体偏心率平方
static double a = _EQURAD; static double a = _EQURAD; // 地球椭球体长半轴
static double ra2 = 1/(_EQURAD*_EQURAD); static double ra2 = 1/(_EQURAD*_EQURAD); // 地球椭球体长半轴平方的倒数
//static double e = sqrt(E2); //static double e = sqrt(E2);
static double e2 = E2; static double e2 = E2; // 地球椭球体偏心率平方
static double e4 = E2*E2; static double e4 = E2*E2; // 地球椭球体偏心率平方的平方
#undef _EQURAD #undef _EQURAD
#undef _FLATTENING #undef _FLATTENING
@ -56,7 +59,7 @@ static double e4 = E2*E2;
#undef _POLRAD #undef _POLRAD
#undef E2 #undef E2
using namespace std::string_literals; using namespace std::string_literals; // 使用字符串字面量
void void
SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod) SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod)
@ -74,6 +77,10 @@ SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod)
// Define the innermost sphere of small radius as earth center and return the // 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, // 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 ;-) // the Northpole, Hawaii or Wentorf. This one was easy to code ;-)
// 这个函数在地球中心区域失败,所以在这里捕获这个特殊情况。
// 定义最内层的球体为地球中心并返回坐标0/0/-EQURAD。
// 它可以是地球表面上的任何其他地方,
// 北极、夏威夷或文托夫。这个很简单。
geod.setLongitudeRad( 0.0 ); geod.setLongitudeRad( 0.0 );
geod.setLatitudeRad( 0.0 ); geod.setLatitudeRad( 0.0 );
geod.setElevationM( -EQURAD ); geod.setElevationM( -EQURAD );
@ -90,6 +97,11 @@ SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod)
slightly negative values for s due to floating point rounding errors slightly negative values for s due to floating point rounding errors
cause nan for sqrt(s*(2+s)) cause nan for sqrt(s*(2+s))
We can probably clamp the resulting parable to positive numbers 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 ) if( s >= -2.0 && s <= 0.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, // this is just a simplified version of the SGGeodToCart function above,
// substitute h = 0, take the 2-norm of the cartesian vector and simplify // substitute h = 0, take the 2-norm of the cartesian vector and simplify
// 这是一个简化的SGGeodToCart函数的版本
// 将h=0代入取笛卡尔向量的2-范数并简化
double phi = geod.getLatitudeRad(); double phi = geod.getLatitudeRad();
double sphi = sin(phi); double sphi = sin(phi);
double sphi2 = sphi*sphi; double sphi2 = sphi*sphi;
@ -171,19 +185,25 @@ SGGeodesy::SGGeocToCart(const SGGeoc& geoc, SGVec3<double>& cart)
// The XYZ/cartesian coordinate system in use puts the X axis through // 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, // 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). // 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 // All latitude and longitude values are in radians. Altitude is in
// meters, with zero on the WGS84 ellipsoid. // meters, with zero on the WGS84 ellipsoid.
// 所有纬度和经度值都是以弧度为单位。
// 高度是以米为单位零点在WGS84椭球体上。
// //
// The code below makes use of the notion of "squashed" space. This // The code below makes use of the notion of "squashed" space. This
// is a 2D cylindrical coordinate system where the radius from the Z // 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 // axis is multiplied by SQUASH; the earth in this space is a perfect
// circle with a radius of POLRAD. // circle with a radius of POLRAD.
// 下面的代码使用“压缩”空间的观念。
// 这是一个2D圆柱坐标系其中Z轴的半径乘以SQUASH
// 在这个空间中地球是一个完美的圆半径为POLRAD。
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Direct and inverse distance functions // Direct and inverse distance functions
// // 直接和反向距离函数
// Proceedings of the 7th International Symposium on Geodetic // Proceedings of the 7th International Symposium on Geodetic
// Computations, 1985 // Computations, 1985
// //
@ -204,6 +224,7 @@ static inline double M0( double e2 ) {
// given, lat1, lon1, az1 and distance (s), calculate lat2, lon2 // given, lat1, lon1, az1 and distance (s), calculate lat2, lon2
// and az2. Lat, lon, and azimuth are in degrees. distance in meters // and az2. Lat, lon, and azimuth are in degrees. distance in meters
// 给定起始点经纬度和方位角以及距离,计算目标点经纬度和方位角
static int _geo_direct_wgs_84 ( double lat1, double lon1, double az1, static int _geo_direct_wgs_84 ( double lat1, double lon1, double az1,
double s, double *lat2, double *lon2, double s, double *lat2, double *lon2,
double *az2 ) double *az2 )

View File

@ -1,70 +1,95 @@
// SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de> // SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de>
// SGGeodesy 头文件
// 包含了一系列地理计算相关的函数,包括地球参数、坐标转换、距离计算等
#ifndef SGGeodesy_H #ifndef SGGeodesy_H
#define SGGeodesy_H #define SGGeodesy_H
class SGGeodesy { class SGGeodesy {
public: public:
// Hard numbers from the WGS84 standard. // Hard numbers from the WGS84 standard.
static const double EQURAD; static const double EQURAD; // 地球赤道半径
static const double iFLATTENING; static const double iFLATTENING; // 地球扁率
static const double SQUASH; static const double SQUASH; // 地球压缩率
static const double STRETCH; static const double STRETCH; // 地球拉伸率
static const double POLRAD; static const double POLRAD; // 地球极半径
/// Takes a cartesian coordinate data and returns the geodetic /// Takes a cartesian coordinate data and returns the geodetic
/// coordinates. /// coordinates.
// 将ECEF坐标转换为地理坐标
static void SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod); static void SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod);
/// Takes a geodetic coordinate data and returns the cartesian /// Takes a geodetic coordinate data and returns the cartesian
/// coordinates. /// coordinates.
// 将地理坐标转换为ECEF坐标
static void SGGeodToCart(const SGGeod& geod, SGVec3<double>& cart); static void SGGeodToCart(const SGGeod& geod, SGVec3<double>& cart);
/// Takes a geodetic coordinate data and returns the sea level radius. /// 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 /// Takes a cartesian coordinate data and returns the geocentric
/// coordinates. /// coordinates.
// 将ECEF坐标转换为地心坐标
static void SGCartToGeoc(const SGVec3<double>& cart, SGGeoc& geoc); static void SGCartToGeoc(const SGVec3<double>& cart, SGGeoc& geoc);
/// Takes a geocentric coordinate data and returns the cartesian /// Takes a geocentric coordinate data and returns the cartesian
/// coordinates. /// coordinates.
// 将地心坐标转换为ECEF坐标
static void SGGeocToCart(const SGGeoc& geoc, SGVec3<double>& cart); static void SGGeocToCart(const SGGeoc& geoc, SGVec3<double>& cart);
// Geodetic course/distance computation // Geodetic course/distance computation
// 给定起始点地理坐标和方位角以及距离,计算目标点经纬度和目标点看起始点的方位角
static bool direct(const SGGeod& p1, double course1, static bool direct(const SGGeod& p1, double course1,
double distance, SGGeod& p2, double& course2); double distance, SGGeod& p2, double& course2);
/// overloaded version of above, returns new value directly, throws /// overloaded version of above, returns new value directly, throws
/// an sg_exception on failure. /// an sg_exception on failure.
// 给定起始点地理坐标和方位角以及距离,计算目标点地理坐标
static SGGeod direct(const SGGeod& p1, double course1, static SGGeod direct(const SGGeod& p1, double course1,
double distance); double distance);
// 给定起始点和目标点地理坐标,计算起始点看目标点的方位角和目标点看起始点的方位角以及距离
static bool inverse(const SGGeod& p1, const SGGeod& p2, double& course1, static bool inverse(const SGGeod& p1, const SGGeod& p2, double& course1,
double& course2, double& distance); double& course2, double& distance);
// 给定起始点和目标点地理坐标,计算起始点看目标点的方位角
static double courseDeg(const SGGeod& from, const SGGeod& to); static double courseDeg(const SGGeod& from, const SGGeod& to);
// 给定起始点和目标点地理坐标,计算起始点和目标点之间的距离(单位:米)
static double distanceM(const SGGeod& from, const SGGeod& to); static double distanceM(const SGGeod& from, const SGGeod& to);
// 给定起始点和目标点地理坐标,计算起始点和目标点之间的距离(单位:海里)
static double distanceNm(const SGGeod& from, const SGGeod& to); static double distanceNm(const SGGeod& from, const SGGeod& to);
// Geocentric course/distance computation // Geocentric course/distance computation
// 给定起始点地心坐标和方位角(单位:弧度)以及距离(单位:米),计算目标点地心坐标
static void advanceRadM(const SGGeoc& geoc, double course, double distance, static void advanceRadM(const SGGeoc& geoc, double course, double distance,
SGGeoc& result); SGGeoc& result);
// 给定起始点地心坐标和方位角(单位:度)以及距离(单位:米),计算目标点地心坐标
static SGGeoc advanceDegM(const SGGeoc &geoc, double course, double distance); static SGGeoc advanceDegM(const SGGeoc &geoc, double course, double distance);
// 给定起始点和目标点地心坐标,计算起始点和目标点之间的方位角(单位:弧度)
static double courseRad(const SGGeoc& from, const SGGeoc& to); static double courseRad(const SGGeoc& from, const SGGeoc& to);
// 给定起始点和目标点地心坐标,计算起始点和目标点之间的距离(单位:弧度)
static double distanceRad(const SGGeoc& from, const SGGeoc& to); static double distanceRad(const SGGeoc& from, const SGGeoc& to);
// 给定起始点和目标点地心坐标,计算起始点和目标点之间的距离(单位:米)
static double distanceM(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 * compute the intersection of two (true) radials (in degrees), or return false
* if no intersection culd be computed. * if no intersection culd be computed.
*/ */
// 给定两个点地心坐标和方位角,计算两个方向向量之间的交点
static bool radialIntersection(const SGGeoc& a, double aRadial, static bool radialIntersection(const SGGeoc& a, double aRadial,
const SGGeoc& b, double bRadial, SGGeoc& result); const SGGeoc& b, double bRadial, SGGeoc& result);
// 给定两个点地理坐标和方位角,计算两个方向向量之间的交点
static bool radialIntersection(const SGGeod& a, double aRadial, static bool radialIntersection(const SGGeod& a, double aRadial,
const SGGeod& b, double bRadial, SGGeod& result); const SGGeod& b, double bRadial, SGGeod& result);
}; };

View File

@ -1,6 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de> // SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de>
// SGMath 头文件
// 包含了一系列数学相关的头文件
#ifndef SGMath_H #ifndef SGMath_H
#define SGMath_H #define SGMath_H
@ -10,13 +13,13 @@
#include "SGMathFwd.hxx" #include "SGMathFwd.hxx"
#include "SGCMath.hxx" #include "SGCMath.hxx" // 引入了std标准数学库
#include "SGLimits.hxx" #include "SGLimits.hxx" // 引入了std标准库的limits头文件定义了用于SG的limits类
#include "SGMisc.hxx" #include "SGMisc.hxx" // 提供了一系列数学计算函数,包括最大值、最小值、无溢出加法、渐进、幂运算、归一化、四舍五入等
#include "SGGeodesy.hxx" #include "SGGeodesy.hxx" // 包含了一系列地理计算相关的函数,包括地球参数、坐标转换、距离计算等
#include "SGVec2.hxx" #include "SGVec2.hxx" // 定义了2D向量类SGVec2提供了向量运算、点积、叉积等操作
#include "SGVec3.hxx" #include "SGVec3.hxx" // 定义了3D向量类SGVec3提供了向量运算、点积、叉积等操作
#include "SGVec4.hxx" #include "SGVec4.hxx" // 定义了4D向量类SGVec4提供了向量运算、点积、叉积等操作
#include "SGGeoc.hxx" #include "SGGeoc.hxx"
#include "SGGeod.hxx" #include "SGGeod.hxx"
#include "SGQuat.hxx" #include "SGQuat.hxx"

View File

@ -1,6 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de> // SPDX-FileCopyrightText: 2006 Mathias Froehlich <mathias.froehlich@web.de>
// 数学工具类
// 提供了一系列数学计算函数,包括最大值、最小值、无溢出加法、渐进、幂运算、归一化、四舍五入等
#ifndef SGMisc_H #ifndef SGMisc_H
#define SGMisc_H #define SGMisc_H
@ -26,11 +29,15 @@ public:
{ return max(max(max(a, b), c), d); } { return max(max(max(a, b), c), d); }
// clip the value of a to be in the range between and including _min and _max // 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) static T clip(const T& a, const T& _min, const T& _max)
{ return max(_min, min(_max, a)); } { return max(_min, min(_max, a)); }
/// Add two (integer) values taking care of overflows. /// Add two (integer) values taking care of overflows.
// 无溢出加法
// 如果b大于0则检查a+b是否溢出如果溢出则返回SGLimits<T>::max()否则返回a+b
// 如果b小于0则检查a+b是否溢出如果溢出则返回SGLimits<T>::min()否则返回a+b
static T addClipOverflow(T a, T b) static T addClipOverflow(T a, T b)
{ {
if( b > 0 ) if( b > 0 )
@ -48,6 +55,7 @@ public:
} }
/// Add two (integer) values in place, taking care of overflows. /// Add two (integer) values in place, taking care of overflows.
// 无溢出原位置加法
static T& addClipOverflowInplace(T& a, T b) static T& addClipOverflowInplace(T& a, T b)
{ {
return a = addClipOverflow(a, b); return a = addClipOverflow(a, b);
@ -61,6 +69,7 @@ public:
* @param rate Max. change rate/sec * @param rate Max. change rate/sec
* @param dt Time step (sec) * @param dt Time step (sec)
*/ */
// 渐进: var 将以指定的速率 rate 按时间 dt 的递增向 target 渐进。
template<class Var> template<class Var>
static T seek(Var& var, T target, T rate, T dt) static T seek(Var& var, T target, T rate, T dt)
{ {
@ -76,6 +85,7 @@ public:
* @tparam N Exponent * @tparam N Exponent
* @param base Base * @param base Base
*/ */
// 幂运算
template<int N> template<int N>
static T pow(T base) static T pow(T base)
{ {
@ -101,7 +111,8 @@ public:
static T deg2rad(const T& val) static T deg2rad(const T& val)
{ return val*pi()/180; } { 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 static T
normalizePeriodic(const T& min, const T& max, const T& value) normalizePeriodic(const T& min, const T& max, const T& value)
{ {
@ -117,22 +128,28 @@ public:
return normalized; 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 static T
normalizeAngle(const T& angle) normalizeAngle(const T& angle)
{ return normalizePeriodic(-pi(), pi(), 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 static T
normalizeAngle2(const T& angle) normalizeAngle2(const T& angle)
{ return normalizePeriodic(0, twopi(), angle); } { return normalizePeriodic(0, twopi(), angle); }
// 四舍五入:将 v 四舍五入到最接近的整数,返回结果为 T 类型
static T round(const T& v) static T round(const T& v)
{ return floor(v + T(0.5)); } { return floor(v + T(0.5)); }
// 将 v 四舍五入到最接近的整数
static int roundToInt(const T& v) static int roundToInt(const T& v)
{ return int(round(v)); } { return int(round(v)); }
// Linear interpolation between two arbitrary typed values // Linear interpolation between two arbitrary typed values
// 线性插值:在 val0 和 val1 之间进行线性插值t 是插值因子,取值范围为 [0, 1]
template<typename S> template<typename S>
static S lerp(const S& val0, const S& val1, const T& t) static S lerp(const S& val0, const S& val1, const T& t)
{ return val0*(T(1) - t) + val1*t; } { return val0*(T(1) - t) + val1*t; }
@ -144,9 +161,11 @@ public:
return std::isnan(v); return std::isnan(v);
} }
// 判断两个值是否相等
static bool eq(const T& a, const T& b, const T& epsilon = SGLimits<T>::epsilon()) static bool eq(const T& a, const T& b, const T& epsilon = SGLimits<T>::epsilon())
{ return std::abs(a - b) < epsilon; } { return std::abs(a - b) < epsilon; }
// 判断两个值是否不相等
static bool neq(const T& a, const T& b, const T& epsilon = SGLimits<T>::epsilon()) static bool neq(const T& a, const T& b, const T& epsilon = SGLimits<T>::epsilon())
{ return !eq(a, b, epsilon); } { return !eq(a, b, epsilon); }
}; };

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-License-Identifier: LGPL-2.1-or-later
// SPDX-FileCopyrightText: 2016-2017 Erik Hofman <erik@ehofman.com> // SPDX-FileCopyrightText: 2016-2017 Erik Hofman <erik@ehofman.com>
// sim4d一个向量类支持4个或更少元素的向量主要是实现向量的运算优化
#pragma once #pragma once
#include <cstdint> #include <cstdint>
@ -17,6 +18,7 @@ template<typename T, int N> class simd4_t;
namespace simd4 namespace simd4
{ {
// min函数返回两个向量中各分量的最小值
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> min(simd4_t<T,N> v1, const simd4_t<T,N>& v2) { inline simd4_t<T,N> min(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
@ -25,6 +27,7 @@ inline simd4_t<T,N> min(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
return v1; return v1;
} }
// max函数返回两个向量中各分量的最大值
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> max(simd4_t<T,N> v1, const simd4_t<T,N>& v2) { inline simd4_t<T,N> max(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
@ -33,6 +36,7 @@ inline simd4_t<T,N> max(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
return v1; return v1;
} }
// abs函数返回向量中各分量的绝对值
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> abs(simd4_t<T,N> v) { inline simd4_t<T,N> abs(simd4_t<T,N> v) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
@ -41,6 +45,7 @@ inline simd4_t<T,N> abs(simd4_t<T,N> v) {
return v; return v;
} }
// magnitude2函数返回向量中各分量的平方和即二范数的平方
template<typename T, int N> template<typename T, int N>
inline T magnitude2(const simd4_t<T,N>& vi) { inline T magnitude2(const simd4_t<T,N>& vi) {
simd4_t<T,N> v(vi); simd4_t<T,N> v(vi);
@ -52,16 +57,19 @@ inline T magnitude2(const simd4_t<T,N>& vi) {
return mag2; return mag2;
} }
// interpolate函数返回两个向量之间的线性插值
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> interpolate(T tau, const simd4_t<T,N>& v1, const simd4_t<T,N>& v2) { inline simd4_t<T,N> interpolate(T tau, const simd4_t<T,N>& v1, const simd4_t<T,N>& v2) {
return v1 + tau*(v2-v1); return v1 + tau*(v2-v1);
} }
// magnitude函数返回向量的二范数
template<typename T, int N> template<typename T, int N>
inline T magnitude(const simd4_t<T,N>& v) { inline T magnitude(const simd4_t<T,N>& v) {
return std::sqrt(magnitude2(v)); return std::sqrt(magnitude2(v));
} }
// normalize函数归一化向量
template<typename T, int N> template<typename T, int N>
inline T normalize(simd4_t<T,N>& v) { inline T normalize(simd4_t<T,N>& v) {
T mag = simd4::magnitude(v); T mag = simd4::magnitude(v);
@ -73,6 +81,7 @@ inline T normalize(simd4_t<T,N>& v) {
return mag; return mag;
} }
// dot函数返回两个向量的点积
template<typename T, int N> template<typename T, int N>
inline T dot(const simd4_t<T,N>& v1, const simd4_t<T,N>& v2) { inline T dot(const simd4_t<T,N>& v1, const simd4_t<T,N>& v2) {
simd4_t<T,N> v(v1*v2); simd4_t<T,N> v(v1*v2);
@ -83,6 +92,7 @@ inline T dot(const simd4_t<T,N>& v1, const simd4_t<T,N>& v2) {
return dp; return dp;
} }
// cross函数返回两个向量的叉积仅三维向量有效
template<typename T> template<typename T>
inline simd4_t<T,3> cross(const simd4_t<T,3>& v1, const simd4_t<T,3>& v2) inline simd4_t<T,3> cross(const simd4_t<T,3>& v1, const simd4_t<T,3>& v2)
{ {
@ -95,45 +105,55 @@ inline simd4_t<T,3> cross(const simd4_t<T,3>& v1, const simd4_t<T,3>& v2)
} /* namespace simd4 */ } /* namespace simd4 */
// simd4_t类支持4个或更少元素的向量主要是实现向量的运算优化
template<typename T, int N> template<typename T, int N>
class simd4_t final class simd4_t final
{ {
private: private:
// 联合体用于存储4个元素的向量或N个元素的向量N<=4
union { union {
T _v4[4]; T _v4[4];
T vec[N]; T vec[N];
}; };
public: public:
// 构造函数初始化为全0
simd4_t(void) { simd4_t(void) {
for (int i=0; i<4; ++i) _v4[i] = 0; for (int i=0; i<4; ++i) _v4[i] = 0;
} }
// 构造函数,初始化为一个标量
simd4_t(T s) { simd4_t(T s) {
for (int i=0; i<N; ++i) vec[i] = s; for (int i=0; i<N; ++i) vec[i] = s;
for (int i=N; i<4; ++i) _v4[i] = 0; for (int i=N; i<4; ++i) _v4[i] = 0;
} }
// 构造函数初始化为二维向量其余维度为0
simd4_t(T x, T y) : simd4_t(x,y,0,0) {} simd4_t(T x, T y) : simd4_t(x,y,0,0) {}
// 构造函数初始化为三维向量其余维度为0
simd4_t(T x, T y, T z) : simd4_t(x,y,z,0) {} simd4_t(T x, T y, T z) : simd4_t(x,y,z,0) {}
// 构造函数,初始化为四维向量
simd4_t(T x, T y, T z, T w) { simd4_t(T x, T y, T z, T w) {
_v4[0] = x; _v4[1] = y; _v4[2] = z; _v4[3] = w; _v4[0] = x; _v4[1] = y; _v4[2] = z; _v4[3] = w;
for (int i=N; i<4; ++i) _v4[i] = 0; for (int i=N; i<4; ++i) _v4[i] = 0;
} }
// 构造函数由一个数组初始化为N维向量
explicit simd4_t(const T v[N]) { explicit simd4_t(const T v[N]) {
std::memcpy(vec, v, sizeof(T[N])); std::memcpy(vec, v, sizeof(T[N]));
for (int i=N; i<4; ++i) _v4[i] = 0; for (int i=N; i<4; ++i) _v4[i] = 0;
} }
// 构造函数由一个M维向量初始化为N维向量M与N均不大于4
template<int M> template<int M>
simd4_t(const simd4_t<T,M>& v) { simd4_t(const simd4_t<T,M>& v) {
std::memcpy(_v4, v.ptr(), sizeof(T[M])); std::memcpy(_v4, v.ptr(), sizeof(T[M]));
for (int i=(M<N)?M:N; i<4; ++i) _v4[i] = 0; for (int i=(M<N)?M:N; i<4; ++i) _v4[i] = 0;
} }
~simd4_t(void) {} // non-virtual intentional // 析构函数
~simd4_t(void) {} // non-virtual intentional // 非虚拟析构函数,故意的
// 返回一个N维数组的引用
inline T (&v4(void))[N] { inline T (&v4(void))[N] {
return vec; return vec;
} }
// 返回一个N维数组的常量引用
inline const T (&v4(void) const)[N] { inline const T (&v4(void) const)[N] {
return vec; return vec;
} }
@ -141,95 +161,104 @@ public:
inline const T (&ptr(void) const)[N] { inline const T (&ptr(void) const)[N] {
return vec; return vec;
} }
// 返回一个N维数组的引用
inline T (&ptr(void))[N] { inline T (&ptr(void))[N] {
return vec; return vec;
} }
// []运算符重载返回第n个元素的常量引用
inline const T& operator[](unsigned n) const { inline const T& operator[](unsigned n) const {
assert(n<N); assert(n<N);
return vec[n]; return vec[n];
} }
// []运算符重载返回第n个元素的引用
inline T& operator[](unsigned n) { inline T& operator[](unsigned n) {
assert(n<N); assert(n<N);
return vec[n]; return vec[n];
} }
// 赋值运算符重载将一个M维向量赋值给一个N维向量
template<int M> template<int M>
inline simd4_t<T,N>& operator=(const simd4_t<T,M>& v) { inline simd4_t<T,N>& operator=(const simd4_t<T,M>& v) {
*this = simd4_t<T,N>(v); *this = simd4_t<T,N>(v);
return *this; return *this;
} }
// +=运算符重载将一个标量加到N维向量的每个元素上
inline simd4_t<T,N>& operator+=(T s) { inline simd4_t<T,N>& operator+=(T s) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] += s; vec[i] += s;
} }
return *this; return *this;
} }
// +=运算符重载将一个N维数组加到该N维向量上
inline simd4_t<T,N>& operator+=(const T v[N]) { inline simd4_t<T,N>& operator+=(const T v[N]) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] += v[i]; vec[i] += v[i];
} }
return *this; return *this;
} }
// +=运算符重载将一个N维向量加到该N维向量上
inline simd4_t<T,N>& operator+=(const simd4_t<T,N>& v) { inline simd4_t<T,N>& operator+=(const simd4_t<T,N>& v) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] += v[i]; vec[i] += v[i];
} }
return *this; return *this;
} }
// -=运算符重载在该N维向量的每个元素上减去一个标量
inline simd4_t<T,N>& operator-=(T s) { inline simd4_t<T,N>& operator-=(T s) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] -= s; vec[i] -= s;
} }
return *this; return *this;
} }
// -=运算符重载在该N维向量上减去一个N维数组
inline simd4_t<T,N>& operator-=(const T v[N]) { inline simd4_t<T,N>& operator-=(const T v[N]) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] -= v[i]; vec[i] -= v[i];
} }
return *this; return *this;
} }
// -=运算符重载在该N维向量上减去一个N维向量
inline simd4_t<T,N>& operator-=(const simd4_t<T,N>& v) { inline simd4_t<T,N>& operator-=(const simd4_t<T,N>& v) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] -= v[i]; vec[i] -= v[i];
} }
return *this; return *this;
} }
// *=运算符重载将该N维向量的每个元素乘以一个标量
inline simd4_t<T,N>& operator*=(T s) { inline simd4_t<T,N>& operator*=(T s) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] *= s; vec[i] *= s;
} }
return *this; return *this;
} }
// *=运算符重载将该N维向量的每个元素乘以一个N维数组每个元素
inline simd4_t<T,N>& operator*=(const T v[N]) { inline simd4_t<T,N>& operator*=(const T v[N]) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] *= v[i]; vec[i] *= v[i];
} }
return *this; return *this;
} }
// *=运算符重载将该N维向量的每个元素乘以一个N维向量的每个元素
inline simd4_t<T,N>& operator*=(const simd4_t<T,N>& v) { inline simd4_t<T,N>& operator*=(const simd4_t<T,N>& v) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] *= v[i]; vec[i] *= v[i];
} }
return *this; return *this;
} }
// /=运算符重载将该N维向量的每个元素除以一个标量
inline simd4_t<T,N>& operator/=(T s) { inline simd4_t<T,N>& operator/=(T s) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] /= s; vec[i] /= s;
} }
return *this; return *this;
} }
// /=运算符重载将该N维向量的每个元素除以一个N维数组每个元素
inline simd4_t<T,N>& operator/=(const T v[N]) { inline simd4_t<T,N>& operator/=(const T v[N]) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] /= v[i]; vec[i] /= v[i];
} }
return *this; return *this;
} }
// /=运算符重载将该N维向量的每个元素除以一个N维向量的每个元素
inline simd4_t<T,N>& operator/=(const simd4_t<T,N>& v) { inline simd4_t<T,N>& operator/=(const simd4_t<T,N>& v) {
for (int i=0; i<N; ++i) { for (int i=0; i<N; ++i) {
vec[i] /= v[i]; vec[i] /= v[i];
@ -238,6 +267,8 @@ public:
} }
}; };
// 以下均为类外重载
// -运算符重载返回一个N维向量的负值
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> operator-(const simd4_t<T,N>& v) { inline simd4_t<T,N> operator-(const simd4_t<T,N>& v) {
simd4_t<T,N> r(T(0)); simd4_t<T,N> r(T(0));
@ -245,36 +276,42 @@ inline simd4_t<T,N> operator-(const simd4_t<T,N>& v) {
return r; return r;
} }
// +运算符重载返回两个N维向量的和
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> operator+(simd4_t<T,N> v1, const simd4_t<T,N>& v2) { inline simd4_t<T,N> operator+(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
v1 += v2; v1 += v2;
return v1; return v1;
} }
// -运算符重载返回两个N维向量的差
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> operator-(simd4_t<T,N> v1, const simd4_t<T,N>& v2) { inline simd4_t<T,N> operator-(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
v1 -= v2; v1 -= v2;
return v1; return v1;
} }
// *运算符重载将一个N维向量乘以一个N维向量对应元素相乘
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> operator*(simd4_t<T,N> v1, const simd4_t<T,N>& v2) { inline simd4_t<T,N> operator*(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
v1 *= v2; v1 *= v2;
return v1; return v1;
} }
// /运算符重载将一个N维向量除以一个N维向量对应元素相除
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> operator/(simd4_t<T,N> v1, const simd4_t<T,N>& v2) { inline simd4_t<T,N> operator/(simd4_t<T,N> v1, const simd4_t<T,N>& v2) {
v1 /= v2; v1 /= v2;
return v1; return v1;
} }
// *运算符重载将一个标量乘以一个N维向量
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> operator*(T f, simd4_t<T,N> v) { inline simd4_t<T,N> operator*(T f, simd4_t<T,N> v) {
v *= f; v *= f;
return v; return v;
} }
// *运算符重载将一个N维向量乘以一个标量
template<typename T, int N> template<typename T, int N>
inline simd4_t<T,N> operator*(simd4_t<T,N> v, T f) { inline simd4_t<T,N> operator*(simd4_t<T,N> v, T f) {
v *= f; v *= f;