如何从向量计算正交平面
How to calculate an orthogonal plane from a vector
我在 space 有一个职位叫 X1。 X1 的速度称为 V1。我需要构建一个垂直于速度矢量的正交平面。平面的原点是 X1。
我需要将平面的两条边变成两个向量,E1 和 E2。边在原点连接。所以三个向量组成一个轴。
我将 GLM 库用于矢量数学。
一般来说,您可以使用四个数字定义 3D 平面,例如 Ax+By+Cz=D。您可以将数字的三元组 (A,B,C) 视为垂直于平面伸出的向量(称为法向量)。
法向量 n = (A,B,C) 仅定义平面的方向,因此根据常数 D 的选择,您会得到距原点不同距离的平面。
如果我没有正确理解你的问题,你要查找的平面的法向量 (A,B,C) = V1 并且常数 D 是使用点积获得的:D = (A,B,C ) 。 X1,即 D = AX1.x + BX1.y + C*X1.z.
请注意,您也可以使用平面 n 的几何方程获得相同的结果。 ((x,y,z) - p0) = 0,其中 p0 是平面上的某个点,在您的例子中是 V1 。 ( (x,y,z) - X1) = 0.
从矢量创建帧的一种方法是使用 Householder transformations。这可能看起来很复杂,但代码很短,至少与使用叉积一样高效,并且不太容易出现舍入错误。此外,完全相同的想法适用于任何维度。
想法是,给定一个向量 v,找到一个将 v 映射到 (1,0,0) 的倍数的 Householder 变换,然后将其逆应用于 (0,1,0) 和 ( 0,0,1) 获取其他帧向量。由于 Householder 转换是它自己的逆转换,并且由于它们易于应用,因此生成的代码相当高效。下面是我使用的 C 代码:
static void make_frame( const double* v, double* f)
{
double lv = hypot( hypot( v[0], v[1]), v[2]); // length of v
double s = v[0] > 0.0 ? -1.0 : 1.0;
double h[3] = { v[0] - s*lv, v[1], v[2]}; // householder vector for Q
double a = 1.0/(lv*(lv + fabs( v[0]))); // == 2/(h'*h)
double b;
// first frame vector is v normalised
b = 1.0/lv;
f[3*0+0] = b*v[0]; f[3*0+1] = b*v[1]; f[3*0+2] = b*v[2];
// compute other frame vectors by applying Q to (0,1,0) and (0,0,1)
b = -v[1]*a;
f[3*1+0] = b*h[0]; f[3*1+1] = 1.0 + b*h[1]; f[3*1+2] = b*h[2];
b = -v[2]*a;
f[3*2+0] = h[0]*b; f[3*2+1] = b*h[1]; f[3*2+2] = 1.0 + b*h[2];
}
我在 space 有一个职位叫 X1。 X1 的速度称为 V1。我需要构建一个垂直于速度矢量的正交平面。平面的原点是 X1。
我需要将平面的两条边变成两个向量,E1 和 E2。边在原点连接。所以三个向量组成一个轴。
我将 GLM 库用于矢量数学。
一般来说,您可以使用四个数字定义 3D 平面,例如 Ax+By+Cz=D。您可以将数字的三元组 (A,B,C) 视为垂直于平面伸出的向量(称为法向量)。
法向量 n = (A,B,C) 仅定义平面的方向,因此根据常数 D 的选择,您会得到距原点不同距离的平面。
如果我没有正确理解你的问题,你要查找的平面的法向量 (A,B,C) = V1 并且常数 D 是使用点积获得的:D = (A,B,C ) 。 X1,即 D = AX1.x + BX1.y + C*X1.z.
请注意,您也可以使用平面 n 的几何方程获得相同的结果。 ((x,y,z) - p0) = 0,其中 p0 是平面上的某个点,在您的例子中是 V1 。 ( (x,y,z) - X1) = 0.
从矢量创建帧的一种方法是使用 Householder transformations。这可能看起来很复杂,但代码很短,至少与使用叉积一样高效,并且不太容易出现舍入错误。此外,完全相同的想法适用于任何维度。
想法是,给定一个向量 v,找到一个将 v 映射到 (1,0,0) 的倍数的 Householder 变换,然后将其逆应用于 (0,1,0) 和 ( 0,0,1) 获取其他帧向量。由于 Householder 转换是它自己的逆转换,并且由于它们易于应用,因此生成的代码相当高效。下面是我使用的 C 代码:
static void make_frame( const double* v, double* f)
{
double lv = hypot( hypot( v[0], v[1]), v[2]); // length of v
double s = v[0] > 0.0 ? -1.0 : 1.0;
double h[3] = { v[0] - s*lv, v[1], v[2]}; // householder vector for Q
double a = 1.0/(lv*(lv + fabs( v[0]))); // == 2/(h'*h)
double b;
// first frame vector is v normalised
b = 1.0/lv;
f[3*0+0] = b*v[0]; f[3*0+1] = b*v[1]; f[3*0+2] = b*v[2];
// compute other frame vectors by applying Q to (0,1,0) and (0,0,1)
b = -v[1]*a;
f[3*1+0] = b*h[0]; f[3*1+1] = 1.0 + b*h[1]; f[3*1+2] = b*h[2];
b = -v[2]*a;
f[3*2+0] = h[0]*b; f[3*2+1] = b*h[1]; f[3*2+2] = 1.0 + b*h[2];
}