vtkMath
vtkMath提供了执行常见数学运算的方法。这些包括提供常数,如Pi;从度到弧度的转换;向量运算,如点积、叉积和向量范数;2x2和3x3矩阵的矩阵行列式;一元多项式求解器;用于随机数生成(仅用于向后兼容)。
常量定义
定义常使用的PI:
static constexpr double Pi() { return 3.141592653589793; }
使用cos(-1)
计算出的PI值为3.1415926535897931
;
基础数据操作
四舍五入
static int Round(float f) { return static_cast<int>(f + (f >= 0.0 ? 0.5 : -0.5)); }
static int Round(double f) { return static_cast<int>(f + (f >= 0.0 ? 0.5 : -0.5)); }
double类型到其他类型转换
在计算中,常会遇到将double类型的值赋值给其他类型,如果直接强制类型转换,会出现精度的下降或数值的溢出;
RoundDoubleToIntegralIfNecessary
将val
值转换到OutT
类型值,可以保证ret
值在OutT
类型的合理范围内,不会溢出;
template <typename OutT>
static void RoundDoubleToIntegralIfNecessary(double val, OutT* ret) {
vtk_detail::RoundDoubleToIntegralIfNecessary(val, ret);
}
整型数的截取
Floor
向下取整,Ceil
向上取整;
inline int vtkMath::Floor(double x)
{
int i = static_cast<int>(x);
return i - (i > x);
}
inline int vtkMath::Ceil(double x)
{
int i = static_cast<int>(x);
return i + (i < x);
}
幂函数
CeilLog2
给出两个不小于x的最小幂的指数。
static int CeilLog2(vtkTypeUInt64 x);
IsPowerOfTwo
函数的功能为:如果整数是2的幂,则返回true。
inline bool vtkMath::IsPowerOfTwo(vtkTypeUInt64 x){
return ((x != 0) & ((x & (x - 1)) == 0));
}
NearestPowerOfTwo
函数的功能为:计算两个不小于x的最近幂。
如果x小于或等于零,则返回值为1;如果结果太大而无法放入整数,则返回值为VTK_INT_MIN。
inline int vtkMath::NearestPowerOfTwo(int x){
unsigned int z = static_cast<unsigned int>(((x > 0) ? x - 1 : 0));
z |= z >> 1;
z |= z >> 2;
z |= z >> 4;
z |= z >> 8;
z |= z >> 16;
return static_cast<int>(z + 1);
}
Factorial
用于计算N阶乘;
static vtkTypeInt64 Factorial(int N);
随机数
VTK中有注释:不要使用Random()
、RandomSeed()
、GetSeed()
、Gaussian()
这是静态的,因此容易出错(特别是对于回归测试),这只是为了向后兼容。
static void RandomSeed(int s);
static int GetSeed();
static double Random();
static double Random(double min, double max);
// 生成按标准正态分布分布的伪随机数。
static double Gaussian();
static double Gaussian(double mean, double std);
抽样和随机数组
Binomial
来自m个对象(m>n)池的n个对象的组合数。
static vtkTypeInt64 Binomial(int m, int n);
BeginCombination
函数功能:开始迭代“m选择n”对象,返回一个由n个整数组成的数组,每个整数从0到m-1。这些整数表示从集合[0,m]中选择的n项。一旦不再需要迭代器,需要调用vtkMath::FreeCombination()
。
NextCombination
给定m,n和[0,m]范围内n个整数的有效组合,此函数将整数更改为m个池中n个项的所有组合序列中的下一个组合。如果该组合是输入时序列中的最后一项,则该组合将保持不变并返回0。否则,将返回1并更新该组合。
FreeCombination
函数功能:释放由BeginCombination
生成的combination
指针;
static int* BeginCombination(int m, int n);
static int NextCombination(int m, int n, int* combination);
static void FreeCombination(int* combination);
最大最小值
template <class T> static T Min(const T& a, const T& b);
template <class T> static T Max(const T& a, const T& b);
赋值
template <class VectorT1, class VectorT2>
static void Assign(const VectorT1& a, VectorT2&& b){
b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
}
static void Assign(const double a[3], double b[3]) { vtkMath::Assign<>(a, b); }
加法
float数组和double数组的加法计算;
static void Add(const float a[3], const float b[3], float c[3]){
for (int i = 0; i < 3; ++i)
{
c[i] = a[i] + b[i];
}
}
static void Add(const double a[3], const double b[3], double c[3]){
for (int i = 0; i < 3; ++i)
{
c[i] = a[i] + b[i];
}
}
减法
数组之间和Vector
之间的减法;
static void Subtract(const float a[3], const float b[3], float c[3]) {
for (int i = 0; i < 3; ++i) {
c[i] = a[i] - b[i];
}
}
static void Subtract(const double a[3], const double b[3], double c[3]) {
for (int i = 0; i < 3; ++i) {
c[i] = a[i] - b[i];
}
}
template <class VectorT1, class VectorT2, class VectorT3>
static void Subtract(const VectorT1& a, const VectorT2& b, VectorT3&& c) {
c[0] = a[0] - b[0];
c[1] = a[1] - b[1];
c[2] = a[2] - b[2];
}
乘法
MultiplyScalar*
用于计算数组与因子s
的乘法;
static void MultiplyScalar(float a[3], float s) {
for (int i = 0; i < 3; ++i) {
a[i] *= s;
}
}
static void MultiplyScalar2D(float a[2], float s) {
for (int i = 0; i < 2; ++i) {
a[i] *= s;
}
}
static void MultiplyScalar(double a[3], double s) {
for (int i = 0; i < 3; ++i) {
a[i] *= s;
}
}
static void MultiplyScalar2D(double a[2], double s) {
for (int i = 0; i < 2; ++i) {
a[i] *= s;
}
}
角度与弧度
常用的角度Radian
与弧度Degree
的计算就是角度到弧度的转换,使用Pi值;
double ratio = 3.1415926 / 180;
double aratio = 180 / 3.1415926;
在VTK中,将PI/180
定义为常量0.017453292519943295
,将180.0/PI
定义为常量57.29577951308232
;
inline float vtkMath::RadiansFromDegrees(float x){
return x * 0.017453292f;
}
inline double vtkMath::RadiansFromDegrees(double x){
return x * 0.017453292519943295;
}
inline float vtkMath::DegreesFromRadians(float x){
return x * 57.2957795131f;
}
inline double vtkMath::DegreesFromRadians(double x){
return x * 57.29577951308232;
}
向量运算
点积
两个向量的点积运算,支持float类型和double类型;
static float Dot(const float a[3], const float b[3]) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
static double Dot(const double a[3], const double b[3]) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
template <typename ReturnTypeT = double, typename TupleRangeT1, typename TupleRangeT2,
typename EnableT = typename std::conditional<!std::is_pointer<TupleRangeT1>::value &&
!std::is_array<TupleRangeT1>::value, TupleRangeT1, TupleRangeT2>::type::value_type>
static ReturnTypeT Dot(const TupleRangeT1& a, const TupleRangeT2& b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
叉积
// Cross product of two 3-vectors. Result (a x b) is stored in c[3].
inline void vtkMath::Cross(const float a[3], const float b[3], float c[3]) {
float Cx = a[1] * b[2] - a[2] * b[1];
float Cy = a[2] * b[0] - a[0] * b[2];
float Cz = a[0] * b[1] - a[1] * b[0];
c[0] = Cx;
c[1] = Cy;
c[2] = Cz;
}
// Cross product of two 3-vectors. Result (a x b) is stored in c[3].
inline void vtkMath::Cross(const double a[3], const double b[3], double c[3]) {
double Cx = a[1] * b[2] - a[2] * b[1];
double Cy = a[2] * b[0] - a[0] * b[2];
double Cz = a[0] * b[1] - a[1] * b[0];
c[0] = Cx;
c[1] = Cy;
c[2] = Cz;
}
外积
计算两个3矢量的外积(浮点型)。
static void Outer(const float a[3], const float b[3], float c[3][3]){
for (int i = 0; i < 3; ++i){
for (int j = 0; j < 3; ++j){
c[i][j] = a[i] * b[j];
}
}
}
static void Outer(const double a[3], const double b[3], double c[3][3]){
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
c[i][j] = a[i] * b[j];
}
}
}