如何找到与给定向量正交的随机向量

时间:2019-04-01 23:17:31

标签: c# unity3d vector trigonometry orthogonal

我有一个包含3个分量(X,Y,Z)的Vector,我想找到一个与给定正交的Vector。由于与任何向量正交的向量都是无限的,所以我只需要一个随机的向量即可。

我尝试使用带有点积公式的方程,因为两个正交向量之间的点积始终为0,因此我设法编写了一些仅在给定向量与轴对齐时才起作用的代码,但是那可能是因为向量的随机分量是X和Y。我实在无法解决这个问题。

我在Unity3D引擎上编写了代码,以便能够轻松地对其进行可视化:

Vector3 GenerateOrthogonal(Vector3 normal)
    {
        float x = Random.Range(1f, -1f);
        float y = Random.Range(1f, -1f);

        float total = normal.x * x + normal.y * y;
        float z = -total / -normal.z;

        return new Vector3(x, y, z).normalized;
    }

1 个答案:

答案 0 :(得分:0)

有几种方法可以做到这一点。我会提供两个。第一个是使用四元数生成随机向量然后将其旋转到位的单线:

Vector3 RandomTangent(Vector3 vector) {
    return Quaternion.FromToRotation(Vector3.forward, vector) * (Quaternion.AngleAxis(Random.Range(0f, 360f), Vector3.forward) * Vector3.right);
}

第二个时间更长,数学上更严格,平台依赖性更小:

Vector3 RandomTangent(Vector3 vector) {
    var normal = vector.normalized;
    var tangent = Vector3.Cross(normal, new Vector3(-normal.z, normal.x, normal.y));
    var bitangent = Vector3.Cross(normal, tangent);
    var angle = Random.Range(-Mathf.PI, Mathf.PI);
    return tangent * Mathf.Sin(angle) + bitangent * Mathf.Cos(angle);
}

以下是关于它们之间差异的一些说明:

  • 这两个函数均会生成具有均匀分布的随机垂直向量(或“切线”)。
  • 您可以通过获取输入和输出之间的角度来测量这些功能的准确性。尽管在大多数情况下会精确到90,但有时会出现很小的偏差,主要是由于浮点舍入误差引起的。
  • 虽然这两个函数都不产生大错误,但是第二个函数生成错误的频率要低得多。
  • 初步实验表明,这些功能的性能足够接近,因此更快的功能可能会因平台而异。第一个实际上是在我的计算机上更快,用于标准Windows版本,这让我措手不及。
  • 如果您准备假定第二个函数的输入是归一化向量,则可以删除输入的显式归一化并提高性能。如果执行此操作,然后将其传递给非归一化向量,则仍然会得到一个垂直向量,但是其长度和分布将不再可靠地均匀。
  • 在传递零向量的退化情况下,第一个函数将在XY平面上生成随机向量,而第二个函数将传播误差并返回零向量本身。