Как повернуть вектор на 90 градусов в произвольном направлении?

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

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

Итак, что должно произойти, учитывая определенный трехмерный вектор v , который может указывать в любом направлении:

  1. Поверните v на 90 градусов в каком-нибудь направлении так, чтобы он оказался на определяемой им плоскости; назови это v'
  2. Поверните v' на произвольную величину в этой плоскости; другими словами, вокруг оси, определяемой v

Или проще говоря:

  1. Повернуть v на 90 градусов в произвольном направлении

Я делаю это на Java; вектор хранится в javax.vecmath.Vector3f. Я знаю об аффинных преобразованиях, но, насколько я понимаю, они вращаются вокруг глобальных осей, и мне нужно вращать свой вектор вокруг локальных осей, определенных им самим, если это имеет смысл.

Может ли кто-нибудь помочь мне решить эту проблему?

поверните на 90 градусов по часовой стрелке и против часовой стрелки в той же плоскости, что и у вашего вектора, а затем «выкрутите» его из плоскости на случайную величину. Я напишу более длинный ответ, когда у меня будет время
@SiddharthBhat Спасибо! :) Я с нетерпением жду этого, так как еще не понимаю, как добиться того, что вы предлагаете.
если ( а б с ) ваше текущее направление, и ( п д р ) новое перпендикулярное направление, то а п + б д + с р "=" 0 где можно выбрать два п , д , р случайным образом и таким образом определяется третий. Это помогает?
@DavidQuinn, я не уверен. Я понимаю такую ​​математику, но я также хотел бы, чтобы новый вектор имел ту же длину, что и исходный, и это кажется сложным, или нет? Я не могу просто выбрать два случайных значения для p и q, а затем определить r, поскольку тогда новый вектор может быть перпендикулярен старому, но он будет иметь случайную длину, верно? Я думаю, что тогда я мог бы довольно легко отрегулировать длину.
@DavidQuinn Подумав об этом еще, и чтобы проверить свое понимание: правда ли, что мне нужно убедиться, что p и q выбираются случайным образом из круглой области, если я хочу убедиться, что все углы равновероятны?
да, вы можете нормализовать новый вектор и соответствующим образом отрегулировать длину
@DavidQuinn - я более формально записал ваш метод в качестве ответа - он намного проще, чем я имел в виду. Надеюсь, ты не против!
@SiddharthBhat: вообще никаких проблем!
@PepijnSchmitz - есть вероятность, что вас не удовлетворил ответ? Я надеялся, что вы примете это, если сочтете это полезным :)

Ответы (2)

Если известен вектор ветвления б "=" ( Икс 0 , у 0 , г 0 ) , то любой перпендикулярный к нему вектор, скажем п "=" ( Икс 1 , у 1 , г 1 ) будет иметь точечный продукт 0 .

Так,

б . п "=" Икс 0 Икс 1 + у 0 у 1 + г 0 г 1 "=" 0 скалярное произведение равно нулю, так как они перпендикулярны
выбрать любой Икс 1 , у 1 вы предпочитаете, и установите г 1 как

г 1 "=" ( Икс 0 Икс 1 + у 0 у 1 ) г 0

Кажется, это самый простой способ получить «случайные» ветки.

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

р "=" л е н × п | п |

где л е н - желаемая длина вектора.

Если г 0 является 0 , то вы получите сингулярность при попытке разделить на г 0 .

Однако, поскольку г 0 является 0 , это никак не влияет на скалярный продукт, поэтому мы можем выбрать любой г 1 мы хотим.

Решить для у 1 выбрав некоторые Икс 1 , а затем разрешить г 1 быть «свободным» (то есть вы можете выбрать любой г 1 е р ). Однако при этом вы столкнетесь с проблемой, если у 0 является 0 также.

Если оба г 0 "=" у 0 "=" 0 , то вы вынуждены установить Икс 1 "=" 0 (чтобы сохранить скалярный продукт как 0 для перпендикулярности) при наличии у 1 , г 1 е р (то есть они бесплатные).

необходимо внести поправку в формулу, если г 0 "=" 0
исправлено, спасибо! Я посоветовал OP просто создать еще один случайный вектор, поскольку маловероятно, что PRNG сгенерирует 0 дважды подряд
@SiddharthBhat Спасибо! У меня есть два вопроса, в основном для проверки моего понимания: во-первых, вы предлагаете сгенерировать другой случайный вектор, если z0 равно 0, но z0 является фиксированной составляющей исходного вектора, так что это не поможет, верно? Кажется, единственный вариант, который у меня есть, если z0 равен 0, - это решить для x1 или y1 ( все они не могут быть равны нулю, но могут быть любые два из них).
Ах, верно. Это вылетело из головы. Да, вы правы, это я что-то напутал. Если г 0 является 0 , то вы можете решить для Икс 1 , у 1 при выборе любого г 1 вы хотите. Я отредактирую ответ, чтобы отразить это.
И во-вторых: правильно ли я понимаю, что если я хочу, чтобы все углы были равновероятными, мне нужно выбрать x1 и y1 как случайную точку из круглой области? Если это квадратная область (например, если я просто случайным образом выберу два значения из некоторого диапазона), то углы квадрата будут перепредставлены, верно?
Да, вы правы - вам нужно подобрать компоненты по кругу. Один из способов сделать это — выбрать θ е [ 0 , 2 π ) а затем установить Икс "=" потому что θ , у "=" грех θ чтобы получить очки на единичном круге.
@SiddharthBhat Если подумать, это должен быть даже не круг, а эллипс, который является проекцией круга на плоскость x, y. Это оказывается сложнее, чем я думал. ;) Есть ли другой способ гарантировать, что все углы будут равновероятными?
Вы можете сделать это и по-другому, выбирая векторы из трехмерной сферы, а затем заставляя их стать ортогональными по отношению к исходному вектору, используя процесс ортогонализации, такой как Gram Schmidt . Ссылка на выбор точек из сферы
Однако я не уверен, что униформа ( Икс , у ) по кругу не получится. Почему бы и нет?
@SiddharthBhat Думаю, это была моя ошибка. Спасибо, я попробую это решение и, скорее всего, вскоре приму ваш ответ!
@PepijnSchmitz - я предполагаю, что решение сработало, так как вы отметили ответ зеленым?
Я реализовал это, и это работает нормально, спасибо! Также спасибо @DavidQuinn, конечно. Я решил проблему z0 = 0, просто найдя y1 в этом случае или x1 , если и z0 , и y0 равны 0.

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

Обратите внимание, что ты ты . Пара ты , ты дополняется в "=" ты × ты к ортонормированному базису р 3 содержащий ты как член. Следует, что ты и в являются ортогональными единичными векторами в плоскости, ортогональной ты .

Чтобы получить случайный единичный вектор ж в этой плоскости порождают равномерно распределенную ф е [ 0 , 2 π ] и положи

ж "=" потому что ф ты + грех ф в   .
Обратите внимание, что вектор ж построенный таким образом, зависит только от ты .

Спасибо! Извините, но я недостаточно знаю об этой математике, чтобы следовать вашему ответу. Как вы думаете, вы могли бы сделать это более понятным для новичка в геометрии? Это существенно отличается от ответа Сиддарта/Дэвида?
@PepijnSchmitz: я делаю стандартную векторную геометрию в р 3 . Основная идея состоит в том, чтобы сохранить предпоследний вектор ветвления. Это позволяет получить явные ортогональные образующие ортогональной плоскости без опасности обращения в нуль знаменателей. – Решение Сиддарта/Дэвида не содержит случайных элементов и сильно зависит от случайных значений координат.
Я думаю, что понимаю, но не думаю, что смогу использовать этот метод, поскольку мои ветви не обязательно прямые, поэтому, когда они порождают подветвь, они больше не обязательно перпендикулярны ветви, от которой они сами ответвились. Хотя вариант интересный, спасибо.