Този проблем може да бъде решен или с ротационна матрица, или с кватерниони, но бих предложил маршрута на ротационната матрица, защото можете едновременно да решите всички точки с едно умножение на матрица.
Матрица на въртене: Ако знаете какви ъгли на Ойлер искате да завъртите, тогава ротационната матрица е правилният начин. За да формирате ротационна матрица, вижте раздела „Основни ротации“ на връзката. Вместо да знаете какво е "нагоре", трябва да знаете колко искате да завъртите обекта си. В този случай (съдейки по предоставените снимки), искате да завъртите на 90 градуса около глобалната ос x (ако искате да го направите около локална ос, трябва знам текущата ориентация на обекта. Мога да разработя в редакция, ако имате нужда от локални ротации). Вашата глобална ротационна матрица ще бъде:
[1 0 0]
[0 0 1]
[0 -1 0]
Изчислих това чрез използване на матрицата Rx(90) в раздела „Основни ротации“. Сега оформете вашите 3D точки във векторни колони. Да кажем, че една точка е на (0,0,1). Тази точка е точно там, където би бил носът, така че очакваме трансформираната точка да бъде (0,1,0). Просто ляво умножете ротационната матрица, за да получите вашия резултат:
[1 0 0] [0] [0]
[0 0 1]*[0]=[1]
[0 -1 0] [1] [0]
Имайте предвид, че в този случай трансформацията е доста тривиална; ние просто изместваме координатите (x остава същото, y се отрича, z и y се разменят). Можете едновременно да трансформирате голям набор от точки, като хоризонтално свържете всички начални координати, за да образувате матрица 3xN и след това умножите наляво ротационната матрица. Например, нека трансформираме точките { (0,0,1), (0,1,0), (1,0,1), (0,0,-1) }:
[1 0 0] [0 0 1 0] [0 0 1 0]
[0 0 1]*[0 1 0 0]=[1 0 1 0]
[0 -1 0] [1 0 1 -1] [0 -1 0 1]
Като напомняне, тази трансформация се върти около глобалния произход (както е илюстрирано от (1,0,1) точка). Ще трябва да извадите центроида от вашите координати, да завъртите и след това да добавите окончателните координати на транслация.
Кватернион: Мога да дам урок тук, но това често се нарича нотация „ос-ъгъл“; можете да го използвате, за да създадете ротационна матрица, която ще завърти вашите точки около произволна единична ос на определен ъгъл. Ето един страхотен урок за това. Кажете ми, ако трябва да допълня в редакция.
РЕДАКТИРАНЕ: в отговор на добавения псевдо код
Ако кръстосаното произведение е 0, тогава линиите са успоредни. Оста на въртене може да бъде ВСЕКИ вектор, перпендикулярен на ВСИЧКИ вход (което го прави перпендикулярен и на двата по дефиниция). Вектор p се дефинира като перпендикулярен, ако dot(v,p)==0, или v.x*p.x+v.y*p.y+v.z*p.z==0 и length(p)>0, така че можем да избираме произволно всяко решение, което удовлетворява тези уравнения.
v1 = vector(0,10,0)
v2 = vector(0,-10,0)
//Not necessary, since you will normalize the cross product result
//v1 = normalize(v1)
//v2 = normalize(v2)
cross = v2.cross(v1) // (0,0,0) and possible divide by 0 if normalized here
if(length(cross)==0){ //either "==0" or "<thresh" where thresh is some very small number
if(v.z!=0)
cross = vector(1,1,-(v1.x+v1.y)/v1.z);
else if(v.y!=0) //is z==0? well here's an identical solution as long as y isn't 0
cross = vector(1,-(v1.x+v1.z)/v.y,1);
else //by this point, v1.x must be the only nonzero remaining point, otherwise it's a null vector
cross = vector(-(v1.y+v1.z)/v.x,1,1);
}
cross=normalize(cross);
angle = acos( normalize(v2.dot(v1)) ) // 180
quat = quaternion(cross,angle)
Не съм запознат с кода на Python, затова добавих еквивалента на C++. Ако някой може да редактира тази публикация, за да я коригира, това би било страхотно.
Редактиране: Не видях коментара ви за acos, съжалявам за това. Съответно промени кода.
person
Suedocode
schedule
27.04.2013