找到垂直于另一个向量的向量的好方法?

时间:2016-12-22 03:22:07

标签: algorithm math

生成垂直于向量的任意向量的好方法是什么?鉴于生成的向量应该是有效的(即除非给定的向量是(0.0, 0.0, 0.0) - 这种情况的输出应该是error)?

我知道有无限的可能向量集(例如见here)。对于任何输入向量,我想要的是严格且无错误的东西。

我尝试设置的内容,此处pn表示垂直向量:p[0] = 0.5*(n[0] + n[1]; p[1] = 0.5*(n[0] - n[1]),然后求解点积方程以找到p[2],但这是有缺陷的当n[2]0时。目前我只能想到繁琐地创建所有案例检查 - 但必须有更好,更优雅的解决方案?

3 个答案:

答案 0 :(得分:4)

选择与给定向量不共线的任意向量。对于"一些僵硬的东西",你可以有一个固定的规则。例如,拾取(1,0,0),除非某些x的向量是(x,0,0);否则选择(0,1,0)。 1 然后取任意向量与输入向量的叉积。这将产生垂直向量。 (当然,这只适用于3D,但这似乎就是你正在做的事情。)

或者(并且这适用于任何维度),沿坐标轴选择单位向量,该单位向量产生具有输入向量的最小(大小)点积。调用此单位向量 e 和输入向量 x 。然后 e - ( e x x 将垂直于 x 。 (很容易检查点积为零:假设,不失一般性, x 是一个单位向量。然后( e - (< em> e • x x )• x =( e x ) - ( e x )( x x )=( e x ) - ( e x )(1)= 0。)

1 更好的规则是选择(1,0,0),(0,1,0)或(0,0,1)中的任何一个形成最小的点积(大小)输入向量。这将为您提供更好的数值稳定性。

答案 1 :(得分:0)

使用标准基础向量获取给定向量的叉积。为了获得最佳精度,采用较不平行的基矢量,即形成最小(绝对)点积的基矢量。不需要大锤子:

if |Nx| = min(|Nx|, |Ny|, |Nz|) => (0, -Nz, Ny)
if |Ny| = min(|Nx|, |Ny|, |Nz|) => (Nz, 0, -Nx)
if |Nz| = min(|Nx|, |Ny|, |Nz|) => (-Ny, Nx, 0)

代码:

double Ax= abs(N.x), Ay= abs(N.y), Az= abs(N.z); 
if (Ax < Ay)
    P= Ax < Az ? Point(0, -N.z, N.y) : Point(-N.y, N.x, 0);
else
    P= Ay < Az ? Point(N.z, 0, -N.x) : Point(-N.y, N.x, 0);

答案 2 :(得分:-1)

您可以使用线性代数或不同的触发函数来解决此问题。

给定一个向量A(xi,yj,zk),其中i,j,kunit axis vectorsx,y,z是该向量的magnitudes,您可以构建line选择points的{​​{1}}上存在的两个单独的projection,以便vectorP1(xi1,yj1,zk1)存在于由向量生成的行P2(xi2,yj2,zk2)L。我们知道A的线段与L = P2 - P1存在或平行,从而为您提供A,如果dot product of 1dot product is 0或{{ 1}}。从这两点开始,你可以使用在这篇文章StackExchange:Mathematics的接受答案中找到的数学在3D中找到该线的斜率,并且一旦你得到该线的斜率和基础数学;任何Orthogonal到他们的产品的行= -1。在2D欧几里得几何中,如果斜率是1/2,则其垂直将具有-2的斜率;因此,一旦找到原始3D矢量生成的那条线的斜率,您需要做的就是找到它的负倒数,但只能在2D中工作,并且使用该值可以使用原始3D上的任意点{{ 1}}生成有效的任意垂直向量。

如果你知道你的三角函数及其属性;特定函数的值为1,-1,0,1 / 2以及其他特定值作为输出,具有相应的特定值作为输入,例如:

Perpendicular

利用这些功能并了解它们的关系并知道两个斜率的乘积= -1。我们可以看到这些函数中最容易使用的是orthogonal其中vector并且知道trig的身份函数,例如Reciprocal,Quotient,Pythagorean,Cofunction,(Even / Odd)同一性使用Sum&amp; S等各种公式。差异,双角度,功率减少,乘积和,乘积和公式以及三角函数的弧函数和反函数您应该能够轻松找到与余弦版本的点和交叉乘积的垂直线通过sin A { 0PI, PI, 2PI, 0deg, 180deg, 360deg } = 0 sin A { PI/2, 90deg } = 1 sin A { 3PI/2, 270deg } = -1 cos A { 0PI, 2PI, 0deg, 360deg } = 1 cos A { PI/2, 3PI/2, 90deg, 270deg } = 0 cos A { PI, 180deg } = -1 tan A { 0PI, PI, 2PI, 0deg, 180deg, 360deg } = 0 tan A { PI/4, 45deg } = 1 tan A { PI/2, 3PI/2, 90deg, 270deg } = undefined. 。以下是关于此的更多数学:dot:crosswiki

现在我们知道了一些涉及的数学及其属性,并且我们有一个向量A(x,y,z),我们可以使用以下内容:

cos A

这些为我们提供了构建称为单位向量的基矢量的基础 或者原始矢量的归一化矢量,并且从该归一化矢量中很容易从中知道上面列出的少数特性来计算正交矢量。要标准化矢量以获得其单位矢量,可以使用以下公式或函数:

C ++版本

A = PI or 180 degrees

一旦你有一个归一化向量,向量的总长度= 1.计算这个向量的交叉和点积是非常便宜的,找到一个与它正交的很容易,并计算它将如下

Law of Cosines

以上算法中的以下方法未显示:

  • someTrigFuncToGiveAngle(...);
  • clampAngle(...);
  • vector.rotate(...);

这些可以留给OP作为作业。

所以基本算法如下:

  • 采用原始矢量和任意任意矢量都不能是零矢量
  • 如果要么是0个向量,那么只需返回零向量并用函数完成
  • 规范化两个向量
  • 计算两个矢量之间的余弦角
  • 从余弦角度获取实际角度
  • [0,180]
  • 之间的夹角
  • 检查Angle = 0;如果为True - 并行将x分量改为1并再次调用传递更新的任意向量
  • 检查Angle = 90;如果为True - 已经正交返回任意
  • 如果Angle是&lt; 90;通过从90减去所需角度然后通过它旋转任意角度来计算所需角度并返回正交或所需矢量
  • 如果Angle是&gt; 90;通过从中减去90然后通过它旋转任意角度来计算所需角度并返回正交或所需矢量