1
This commit is contained in:
parent
6ead17de2f
commit
c8b1414fca
@ -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>&
|
||||||
|
@ -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
|
||||||
|
@ -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 )
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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"
|
||||||
|
@ -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); }
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user