【问题标题】:What is a formula to get a vector perpendicular to another vector?得到一个向量垂直于另一个向量的公式是什么?
【发布时间】:2022-01-15 13:03:18
【问题描述】:

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

也就是说,给定一个向量 A,什么是公式 f(angle,modulus),它给出了一个垂直于 A 的向量,具有所述模数并旋转了一个角度?

【问题讨论】:

  • 两件事:第一,我们是在二维中操作吗?三? n?其次,你的标题说“垂直”,但问题主体说“旋转了一个角度”——这个角度会不会超过 90 度?
  • 在 3 维中,有无限多个不同的向量(二维向量空间)垂直于给定向量。公式不会生成单个向量。

标签: math vector formula algebra


【解决方案1】:

用与A不共线的另一个向量C计算cross productAxC

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

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

【讨论】:

  • 只有一个向量,我想要一个公式,它给出一个垂直于它的向量,它是角度和长度的函数。
  • Dokkat,你在描述中一直看到两个向量的原因是因为给定第一个向量 V1,有许多向量 V2 垂直于 V1。在 2D 空间中,至少有两个长度为 1 的向量。在 3D 空间中,有无限多个垂直于 V1 的向量!您要查找的是任意一个 V2(与 V1 相同),或者您要检测 (V1,V2) 是否垂直。
【解决方案2】:

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

所以:v1(x1, y1, z1), v2(x2, y2, z2)

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

你知道(x1, y1, z1)。任意输入x2y2,就会收到对应的z2

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

注意z1 是否为0。然后你在飞机上。

【讨论】:

  • 是的。你有一个向量给定v1(x1, y1, z1)
  • 正如您所提到的,如果 z1 为 0,这将失败,但是在这种情况下,问题在数学上仍然完全有效。例如,找到一个垂直于 [1,0,0] 的向量。 z1 是 0,但 [0,1,0] 绝对是一个仍然垂直于 [1,0,0] 的向量。请参阅我的答案以了解另一种方法。
【解决方案3】:

一种方法是找到从正 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: Rotation matrix from axis and angle

另一种方法是使用quaternion rotation。需要多花点心思,但要跟踪的数字更少。

【讨论】:

    【解决方案4】:
    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 &lt; a 然后是 max(a,b) = max(a,b,c),然后是 vector(b,-a,0).length() &gt; max(a,b) = max(a,b,c) ,并且由于 max(a,b,c) 不应该接近于零,所以向量也是。 c &gt; a 的情况类似。

    【讨论】:

    • 仅供参考,我遍历了 10,000 个随机单位向量,并确保所有向量的 dot(vec, above_func(vec)) == 0 (我懒得尝试分析验证稳定性,所以这是我的下一个最好的选项)。效果很好。
    • 如果向量是例如 (a=0, b=0, c=-1), c
    • @GiovanniFunchal 事实上,正如您提到的那样,即使对于“好”向量,“max(a,b,c) 不应接近于零”的声明也可能是错误的。应该使用 L-infinity norm 而不是 max 来更正解释,并且 c 更改
    【解决方案5】:

    我相信这应该产生一个垂直于给定向量vec 的任意向量,同时保持数值稳定,而不管vec 的角度如何(假设vec 的大小不接近于零)。假设 Vec3D 是一个任意数值类型的三维向量。

    Vec3D arbitrary_orthogonal(Vec3D vec)
    {
      bool b0 = (vec[0] <  vec[1]) && (vec[0] <  vec[2]);
      bool b1 = (vec[1] <= vec[0]) && (vec[1] <  vec[2]);
      bool b2 = (vec[2] <= vec[0]) && (vec[2] <= vec[1]);
    
      return cross(vec, Vec3D(int(b0), int(b1), int(b2)));
    }
    

    非正式解释

    恰好 1 个并且只有 1 个布尔值被设置;如果维度N 的大小严格小于所有后续维度且不大于所有先前维度,则设置bN。然后,我们有一个具有单个非零维度的单位向量,该维度对应于vec 中的最小幅度维度。这个与vec 的叉积通过叉积的定义与vec 正交。现在考虑只有当两个向量非常接近时,叉积在数值上是不稳定的。考虑我们的单位向量仅在一个维度上很大,并且该维度对应于 vec 较小的维度。因此保证在取叉积之前与vec 松散正交,在vec 的所有维度都相等的情况下正交性最小。在这种最小正交的情况下,我们仍然是相当正交的,因为我们的单位向量除了一维 0 之外,而 vec 都相等。因此,我们避免了取两个几乎对齐的向量的叉积的不稳定情况。

    【讨论】:

    • 补充说明,希望对您有所帮助。
    【解决方案6】:

    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 之间的值进行浮点运算。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-18
      • 1970-01-01
      • 2011-09-01
      • 2016-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多