获得一个向量垂直于另一个向量的公式是什么?

问题描述 投票:0回答:6

获得位于垂直于向量 A 的平面上的三维向量 B 的公式是什么?

也就是说,给定一个向量 A,公式 f(角度,模数) 给出一个垂直于 A 的向量,用所述模数旋转一个角度?

math vector formula algebra
6个回答
19
投票

如果两个向量垂直,则它们的点积为零。

所以:

v1(x1, y1, z1), v2(x2, y2, z2)

=> x1 * x2 + y1 * y2 + z1 * z2 = 0

你知道

(x1, y1, z1)
。任意输入
x2
y2
,您将收到相应的
z2

z1 * z2 = -x1 * x2 - y1 * y2
=> z2 = (-x1 * x2 - y1 * y2) / z1

请注意

z1
是否为
0
。然后你就在飞机上了。


16
投票
function (a,b,c)
{
    return (-b,a,0)
}

但是当 a,b 接近 0 时,这个答案在数值上不稳定。

为了避免这种情况,请使用:

function (a,b,c) 
{
    return  c<a  ? (b,-a,0) : (0,-c,b) 
}

上面的答案是数值稳定的,因为如果

c < a
然后
max(a,b) = max(a,b,c)
,然后
vector(b,-a,0).length() > max(a,b) = max(a,b,c)
,并且由于
max(a,b,c)
不应该接近于零,所以向量也是如此。
c > a
情况类似。


10
投票

计算 叉积

AxC
与另一个与
C
不共线的向量
A

垂直于

A
的平面上有许多可能的方向。如果你真的不在乎选择哪一个,只需创建一个与
C
不共线的任意向量
A
:

if (A2 != 0 || A3 != 0)
    C = (1, 0, 0);
else
    C = (0, 1, 0);
B = A x C; 

6
投票

我相信这应该产生一个垂直于给定向量

vec
的任意向量,同时保持数值稳定,无论
vec
的角度如何(假设
vec
的大小不接近于零)。假设 Vec3D 是任意数值类型的三维向量。

Vec3D arbitrary_orthogonal(Vec3D vec)
{
  bool b0 = (abs(vec[0]) <  abs(vec[1])) && (abs(vec[0]) <  abs(vec[2]));
  bool b1 = (abs(vec[1]) <= abs(vec[0])) && (abs(vec[1]) <  abs(vec[2]));
  bool b2 = (abs(vec[2]) <= abs(vec[0])) && (abs(vec[2]) <= abs(vec[1]));

  return cross(vec, Vec3D(int(b0), int(b1), int(b2)));
}

非正式解释

恰好 1 个且仅 1 个布尔值被设置;如果维度

bN
的大小严格小于所有后续维度且不大于所有先前维度,则设置
N
。然后我们就有了一个具有单个非零维度的单位向量,它对应于
vec
中最小量值的维度。根据叉积的定义,它与
vec
的叉积与
vec
正交。现在考虑一下,只有当两个向量非常紧密地对齐时,叉积在数值上才不稳定。考虑我们的单位向量仅在一个维度上很大,并且该维度对应于
vec
较小的维度。因此,在进行叉积之前,可以保证与
vec
松散正交,在
vec
的所有维度都相等的情况下,正交性最小。在这种最不正交的情况下,我们仍然是 相当 正交的,因为我们的单位向量除了一维 0 之外的所有维度都是 0,而
vec
都相等。因此,我们避免了对两个几乎对齐的向量进行叉积的不稳定情况。

感谢 Goularou 发现错误。


3
投票

q4w56 几乎已经成为一个强大的解决方案。问题:1)没有考虑缩放。 2)在应该比较两个变量之间的大小时却没有比较。

scale = |x| + |y| + |z|

if scale == 0:
  return (0,0,0)

x = x/scale
y = y/scale
z = z/scale

if |x| > |y|:
  return (z, 0,-x)
else:
  return (0, z,-y)

在处理非常大或非常小的数字时,缩放非常重要。另外,一般来说,您最好对 0 到 1 之间的值进行浮点运算。


2
投票

一种方法是找到从正 z 轴(或任何其他轴)到给定向量的旋转变换。然后使用此变换来变换

<modulus * cos(angle), modulus * sin(angle), 0>

def getPerpendicular(v1,modulus,angle):
    v2 = vector(0,0,1)
    v1_len = v2.length()

    axis = v1.cross_product(v2)
    sinAngle = axis.length() / v1_len       # |u x v| = |u| * |v| * sin(angle)
    cosAngle = v1.dot_product(v2) / v1_len  # u . v = |u| * |v| * cos(angle)
    axis = axis.normalize()
    # atan2(sin(a), cos(a)) = a, -pi < a < pi
    angle = math.atan2(sinAngle, cosAngle)

    rotationMatrix = fromAxisAngle(axis, angle)

    # perpendicular to v2
    v3 = vector(modulus*cos(angle),modulus*sin(angle),0)

    return rotationMatrix.multiply(v3);

要计算旋转矩阵,请参阅这篇文章:WP:根据轴和角度计算旋转矩阵

另一种方法是使用四元数旋转。需要你花更多时间思考,但要跟踪的数字却更少。

© www.soinside.com 2019 - 2024. All rights reserved.