Вектор возмущения на некоторый угол - PullRequest
3 голосов
/ 17 апреля 2010

У меня есть единичный вектор в трехмерном пространстве, направление которого я хочу возмущать на некоторый угол в диапазоне от 0 до тета, при этом положение вектора остается неизменным. Как я могу это сделать?

Спасибо.

РЕДАКТИРОВАТЬ: После размышления о том, как я поставил вопрос, он кажется слишком общим. Я попытаюсь сделать это более конкретным: предположим, что вектор происходит от поверхности объекта (то есть сферы, круга, прямоугольника, линии, цилиндра, конуса). Если существуют разные методы для определения нового направления для каждого из этих объектов, тогда предоставление помощи для сферы - это нормально.

РЕДАКТИРОВАТЬ 2: Я собирался напечатать это в комментарии, но это было слишком много.

Итак, у меня есть orig_vector, который я хочу возмущать в некотором направлении от 0 до theta. theta можно представить как формирующий конус вокруг моего вектора (с theta, являющимся углом между центром и одной стороной конуса), и я хочу создать новый вектор внутри этого конуса. Я могу создать точку, лежащую на плоскости, касательной к моему вектору, и, таким образом, создать единичный вектор в направлении точки, назовем ее rand_vector. В это время I orig_vector и t rand_vector представляют собой два единичных вектора, перпендикулярных друг другу.

Я генерирую свой первый угол, angle1 между 0 и 2pi, и поворачиваю rand_vector вокруг orig_vector на angle1, образуя rand_vector2. Я посмотрел ресурс онлайн, и он сказал, что второй угол, angle2 должен быть между 0 и sin(theta) (где theta - исходный угол "конуса"). Затем я поворачиваю rand_vector2 на acos(angle2) вокруг вектора, заданного перекрестным произведением между rand_vector2 и orig_vector.

Когда я делаю это, я не получаю желаемых результатов. То есть, когда theta=0, я все еще получаю возмущенные векторы, и я ожидаю получить orig_vector. Если кто-то может объяснить причину углов и почему они такие, как я, я был бы очень признателен.

РЕДАКТИРОВАТЬ 3: Это окончательное редактирование, я обещаю =). Поэтому я исправил свою ошибку, и все, что я описал выше, работает (это была ошибка реализации, а не ошибка теории). Тем не менее, мой вопрос об углах (то есть почему angle2 = sin(theta)*rand() и почему perturbed_vector = rand_vector2.Rotate(rand_vector2.Cross(orig_vector), acos(angle2)). Большое спасибо!

Ответы [ 6 ]

7 голосов
/ 18 апреля 2010

Вот алгоритм, который я использовал для решения такой проблемы раньше. Это было описано в Ray Tracing News .

1) Создайте третий вектор перпендикулярно двум другим, чтобы построить ортогональный базис:

cross_vector = unit( cross( orig_vector, rand_vector ) )

2) Выберите два одинаковых случайных числа в [0,1]:

s = rand( 0, 1 )
r = rand( 0, 1 )

3) Пусть h - косинус угла конуса:

h = cos( theta )

4) Измените равномерную выборку на сфере, чтобы выбрать случайный вектор в конусе вокруг + Z:

phi = 2 * pi * s
z = h + ( 1 - h ) * r
sinT = sqrt( 1 - z * z )
x = cos( phi ) * sinT
y = sin( phi ) * sinT

5) Изменение базиса для переориентации вокруг исходного угла:

perturbed = rand_vector * x + cross_vector * y + orig_vector * z
1 голос
/ 17 апреля 2010

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

Однако ось вращения должна быть под прямым углом к ​​вашему начальному вектору, чтобы получить ожидаемую величину вращения. Если ось вращения не лежит в плоскости, перпендикулярной вашему вектору, результат будет несколько отличаться от тета.

При этом, если у вас уже есть вектор под прямым углом к ​​тому, который вы хотите возмущать, и вы не придирчивы к направлению возмущения, вы можете так же легко взять линейная комбинация вашего начального вектора с перпендикулярным, при необходимости настройте величину.

Т.е., если P и Q являются векторами, имеющими одинаковую величину и перпендикулярными, и вы хотите повернуть P в направлении Q, то вектор R определяется как R = [P cos (theta) + Q sin (theta)] будет соответствовать заданным вами ограничениям. Если P и Q имеют различную величину, тогда будет некоторое масштабирование.

0 голосов
/ 14 декабря 2017

Мой код в единстве - проверено и работает:

/*
 *  this is used to perturb given vector 'direction' by changing it by angle not more than 'angle' vector from 
 *  base direction. Used to provide errors for player playing algorithms 
 * 
 */ 
Vector3 perturbDirection( Vector3 direction, float angle ) {
    // division by zero protection 
    if( Mathf.Approximately( direction.z, 0f )) {
        direction.z = 0.0001f; 
    }
    // 1 get some orthogonal vector to direction ( solve direction and orthogonal dot product = 0, assume x = 1, y = 1, then z = as below )) 
    Vector3 orthogonal = new Vector3( 1f, 1f, - ( direction.x + direction.y ) / direction.z );
    // 2 get random vector from circle on flat orthogonal to direction vector. get full range to assume all cone space randomization (-180, 180 )
    float orthoAngle = UnityEngine.Random.Range( -180f, 180f );
    Quaternion rotateTowardsDirection = Quaternion.AngleAxis( orthoAngle, direction );
    Vector3 randomOrtho = rotateTowardsDirection * orthogonal;
    // 3 rotate direction towards random orthogonal vector by vector from our available range 
    float perturbAngle = UnityEngine.Random.Range( 0f, angle );   // range from (0, angle), full cone cover guarantees previous (-180,180) range   
    Quaternion rotateDirection = Quaternion.AngleAxis( perturbAngle, randomOrtho );
    Vector3 perturbedDirection = rotateDirection * direction;
    return perturbedDirection;
}
0 голосов
/ 17 апреля 2010

Как сказано в других комментариях, вы можете вращать свой вектор, используя матрицу вращения.

Матрица вращения имеет два угла, вокруг которых вы поворачиваете свой вектор. Вы можете выбрать их с помощью генератора случайных чисел, но просто выбрать два из плоского генератора не правильно. Чтобы убедиться, что ваш вектор вращения сгенерирован ровно, вы должны выбрать один случайный угол & phi; от плоского генератора, а другой от плоского генератора в cos & theta; это гарантирует, что ваш телесный угловой элемент dcos (& theta;) d & phi; определено правильно (& phi; и & theta; определено как обычно для сферических координат).

Пример : выбор случайного направления без ограничения диапазона, random() генерирует плоскость в [0,1]

angle1 = acos(random())
angle2 = 2*pi*random()
0 голосов
/ 17 апреля 2010

На самом деле, это очень легко сделать. Все, что вам нужно сделать, это умножить ваш вектор на правильную матрицу вращения. Полученный вектор будет вашим повернутым вектором. Теперь, как вы получаете такую ​​матрицу вращения? Это зависит от того, какой 3d-фреймворк / движок вы используете. Любой 3d-фреймворк должен предоставлять функции для получения матриц вращения, обычно как статические методы класса Matrix.

Удачи.

0 голосов
/ 17 апреля 2010

Вас могут заинтересовать преобразования трехмерных координат для изменения угла вектора.

Я не знаю, в скольких направлениях вы хотите изменить угол, но преобразование ваших декартовых координат в сферическиекоординаты должны позволять вам изменять угол по своему усмотрению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...