Как найти случайный вектор, ортогональный данному вектору - PullRequest
1 голос
/ 02 апреля 2019

У меня есть Вектор с 3 компонентами (X, Y, Z), и я хочу найти Вектор, ортогональный данному.Поскольку векторы, ортогональные любому вектору, бесконечны, мне просто нужен случайный вектор.

Я попытался использовать уравнение с формулой Dot Product, поскольку произведение точки между двумя ортогональными векторами всегда равно 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 голосов
/ 02 апреля 2019

Есть несколько способов сделать это. Я предоставлю два. Первый - это однострочник, который использует кватернионы для генерации случайного вектора, а затем поворачивает его на место:

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, а вторая функция будет распространять ошибку и возвращать сам нулевой вектор.
...