我有一个包含 3 个分量(X、Y、Z)的向量,我想找到一个与给定分量正交的向量。由于与任何 Vector 正交的 Vectors 都是无限的,我只需要一个随机的。
我已经尝试使用点积公式的等式,因为两个正交向量之间的点积始终为 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;
}
最佳答案
有几种方法可以做到这一点。我会提供两个。第一个是使用四元数生成随机向量然后将其旋转到位的单行代码:
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 平面上生成随机向量,而第二个函数将传播错误并返回一个零向量本身。
关于c# - 如何找到与给定向量正交的随机向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55464852/