赞
踩
最后编辑于 2024-01-04
本文中所有作为下标的代数均为正整数
向量是表示方向的量, 在不同维度的下向量的数据长度有所不同;
记录时以轴的顺序记录在不同轴上的坐标 : { x(第0轴的坐标) , y(第1轴的坐标), z(第2轴的坐标)…}
代码中使用数值的指针并携带长度属性代替大部分的向量参数, 例 :
// 向量模长
var mag(Idx_VM length, var*& vec);
var mag(Idx_VM length, var*& vec){
var rtn_squares=0;
for(Idx_VM i=0; i<length; ++i) rtn_squares+=vec[i]*vec[i];
return sqrt(rtn_squares);
}
void sum(var*& out, Idx_VM length, var*& vec_0, var*& vec_1){
for(Idx_VM i=0; i<length; ++i) out[i]=vec_0[i]+vec_1[i];
}
void dif(var*& out, Idx_VM length, var*& vec_0, var*& vec_1){
for(Idx_VM i=0; i<length; ++i) out[i]=vec_0[i]-vec_1[i];
}
void np(var*& vec, Idx_VM length, var k){
for(Idx_VM i=0; i<length; ++i) vec[i]*=k;
}
叉积表示一个向量以某方向旋转到另一个向量时的旋转轴
当叉积为0时, 表示两个向量处于同一直线上
2D 叉积, 旋转轴总是在一个虚构的z轴上, 所以直接可以使用一个标量表示, 以叉积的正负表示旋转方向;
起始向量(叉积左向量) (
v
0
v_0
v0 ), 终点向量(叉积右向量) {
v
1
v_1
v1 }
F
c
r
o
s
s
(
v
0
,
v
1
)
=
v
0
×
v
1
=
v
0
x
v
1
y
−
v
0
y
v
1
x
F_{cross}(v_0,v_1)=v_0×v_1=v_{0_x}v_{1_y}-v_{0_y}v_{1_x}
Fcross(v0,v1)=v0×v1=v0xv1y−v0yv1x
+y
^
|*v_0 {1,2}
|
| *v_1 {2,1}
+------------> +x
此处有两点处于坐标系中, 其中x在水平方向的右方向, y在垂直方向的上方向, 虚拟的z在注视内容时的前方向;
v_0={1,2}, v_1={2,1}; cross=1*1-2*2=-3;
此时叉积值为负数, v_0->v_1为顺时针
3D 叉积, 叉积为一个新的向量, 表示旋转时的旋转轴
起始向量(叉积左向量) (
v
0
v_0
v0 ), 终点向量(叉积右向量) {
v
1
v_1
v1 }
F
c
r
o
s
s
(
v
0
,
v
1
)
=
v
0
×
v
1
=
(
v
0
y
v
1
z
−
v
0
z
v
1
y
v
0
z
v
1
x
−
v
0
x
v
1
z
v
0
x
v
1
y
−
v
0
y
v
1
x
)
F_{cross}(v_0,v_1)=v_0×v_1=
代码中使用数值的指针并携带宽高属性代替大部分的矩阵参数, 例 :
// 设置单位矩阵
var*& setup_Matrix__Identity(var*& out, Idx_VM width, Idx_VM height);
本文中, 矩阵下标通常以水平坐标 (u) 和垂直坐标 (v) 表示 (
M
u
,
v
M_{u,v}
Mu,v ) , 本文中所有下标均以0为起点;
如此矩阵M中0列2行的值
M
0
,
2
M_{0,2}
M0,2 = 6
M
=
(
M
0
,
0
,
M
1
,
0
,
M
2
,
0
M
0
,
1
,
M
1
,
1
,
M
2
,
1
M
0
,
2
,
M
1
,
2
,
M
2
,
2
)
=
(
0
,
1
,
2
3
,
4
,
5
6
,
7
,
8
)
M=
物理数据下标计算, 需要宽度参数(w), 水平坐标(u), 垂直坐标(v) : $$ F_i(w,u,v)=v*w+u $
对角线位置, 水平坐标与垂直坐标相同的位置 $$ M_{i,i} $
/** * @brief 将矩阵某个为0的项 通过初等变换的换行操作, 变成非0 * * @param mat 矩阵数据 * @param length 矩阵数据长度 * @param width 矩阵宽度 * @param index 当前下标 * @param v 当前v坐标(行下标) * @param step_length 寻址步长, $1为 ±width * @return 返回是否成功换行 */ bool transformation__ExchangeRow_ToUnZero(var*& mat, Idx_VM length, Idx_VM width, Idx_VM index, Idx_VM v, Idx_VM step_length){ Idx_VM f=step_length>0?1:-1; Idx_VM v_target=v+f; for(Idx_VM i=index+step_length; i>=0&&i<length; i+=step_length, v_target+=f){ if(check_Zero(mat[i])){ // transformation__ExchangeRow 是初等变换的换行操作, 具体实现请翻阅代码 NML_Matrix.hpp , NML_Matrix.cpp transformation__ExchangeRow(mat, width, v, v_target); return true; } } return false; } /** * @brief 使用初等变换计算行列式; * 应在n>4时才使用, n<4时推荐使用 calc_Det__${n} * * @param mat 矩阵数据 (必须是方阵) * @param n 表示这个矩阵是n*n方矩阵 * @return 返回计算的行列式值 */ var calc_Det__Transformation(var*& mat, Idx_VM n){ const Idx_VM length=n*n; var *temp_mat=create_Values__Clone(mat, length); var temp, det=1; Idx_VM _n=n-1; for(Idx_VM uv=0; uv<_n; ++uv){ Idx_VM index_v=uv*n; Idx_VM index_mat__uv=index_v+uv; if(check_Zero(temp_mat[index_mat__uv])){ // 换行 if(!transformation__ExchangeRow_ToUnZero(temp_mat, length, n, index_mat__uv, uv, n)){ delete temp_mat; return 0; } else det=-det; } // 消元 for(Idx_VM index=index_mat__uv+n; index<length; index+=n){ temp=(temp_mat[index])/temp_mat[index_mat__uv]; for(Idx_VM i=uv+1, j=index+1; i<n; ++i, ++j){ temp_mat[j]-=temp*temp_mat[index_v+i]; } } det*=temp_mat[index_mat__uv]; } det*=temp_mat[length-1]; delete temp_mat; return det; }
/** * @brief 寻找最大主元并换行; 换行将副作用到其他矩阵上 * * @param mats 矩阵数据集合 * @param length_g 有多少个矩阵 * @param length 每个矩阵长度 * @param width 矩阵宽度 * @param index 当前下标 * @param v 当前v坐标(行下标) * @param step_length 寻址步长, $1为 ±width * @param _index_m 传入多个矩阵时使用哪个矩阵的值 默认0 * @return 返回是否成功换行 */ bool transformation__ExchangeRow_PivotToMax(var**& mats, Idx_VM length_g, Idx_VM length, Idx_VM width, Idx_VM index, Idx_VM v, Idx_VM step_length, Idx_VM _index_m){ Idx_VM f=step_length>0?1:-1; Idx_VM v_target=v+f; Idx_VM max_row=v; Idx_VM max_row_pivot_index=index; for(Idx_VM i=index+step_length; i>=0&&i<length; i+=step_length, v_target+=f){ if(mats[_index_m][max_row_pivot_index]<mats[_index_m][i]){ max_row_pivot_index=i; max_row=v_target; } } if(check_Zero(mats[_index_m][max_row_pivot_index])){ return false; } if(v!=max_row) transformation__ExchangeRow(mats, length_g, width, v, max_row); return true; } /** * @brief 矩阵求逆 使用初等变换法(高斯乔丹消元法) * * @param out 输出目标 * @param mat 矩阵数据 (必须是方阵) * @param n 表示这个矩阵是n*n方阵 * @return 返回是否成功计算逆矩阵 */ bool setup_Matrix__Inverse__Transformation(var*& out, var*& mat, Idx_VM n){ Idx_VM length=n*n; var *temp_mat=create_Values__Clone(mat, length); // 初始化 out 为增广矩阵 setup_Matrix__Identity(out, n, n); var **mats=new var*[2]{temp_mat, out}; for(Idx_VM uv=0; uv<n; ++uv){ Idx_VM index_v=uv*n; Idx_VM index_mat__uv=index_v+uv; // 换行设置最大主元 if(!transformation__ExchangeRow_PivotToMax(mats, 2, length, n, index_mat__uv, uv, n)) { delete temp_mat; delete mats; return false; } transformation__ScaleRow(mats, 2, n, uv, 1/mats[0][index_mat__uv]); for(Idx_VM i=0, index=0; i<n; ++i, index+=n){ if(i==uv) continue; var k=temp_mat[index+uv]; for(Idx_VM j=0; j<n; ++j){ temp_mat[index+j] -= k * temp_mat[index_v+j]; out[index+j] -= k * out [index_v+j]; } } } delete temp_mat; delete mats; return true; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。