2016-08-05 4 views
9

Я рисую трехмерную сетку, используя метод Mayavi's triangular_mesh. Данные описывают человеческий силуэт, лежащий лицом вниз в трехмерном пространстве (так что cmap можно использовать для обозначения расстояния от камеры).Mayavi: вращать вокруг оси y

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

from mayavi import mlab 

import math 
import numpy as np 
import sys 
import os 


fig = mlab.figure(fgcolor=(0, 0, 0), bgcolor=(1, 1, 1), size=(1920, 980)) 

a = np.array(this_mesh.vertices - refC.conj().transpose()) # this_mesh is an object created from external data files 

this_mesh.faces = this_mesh.faces.astype(int) -1 # mesh data is generated by matlab, which is 1-indexed 

m = mlab.triangular_mesh(x, y, z, this_mesh.faces, opacity=0.75) 

mlab.axes(extent=[-1100, 1100, -1100, 1100, -1100, 1100]) 

без перемещения камеры, силуэт лежит лицом -вниз. Для просмотра модели лицом к лицу я изменяю азимут и высоту камеры, чтобы посмотреть на график сверху вниз. Это показывает силуэт по назначению.

mlab.view(azimuth=0, elevation=180) 
mlab.show() 

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

Усложнение состоит в том, что для получения цветовой карты для информации о глубине я уже перемещаю азимут и высоту представления (как показано в приведенном выше коде). У Mayavi есть больше возможностей для перемещения камеры, чем matplotlib, но у него, похоже, нет возможности вращаться вокруг оси Y, поэтому я предполагаю, что мне нужно выполнить некоторые сложные вычисления по азимуту и ​​высоте, чтобы достичь тот же результат - но я не понимаю, с чего начать (я новичок в работе в 3D-пространстве, и мой мозг так не думает).

Может ли кто-нибудь указать мне правильное направление?

ответ

1

Оказывается, есть немного обходной путь для этого.

Вы можете вращать актеры на своих осях независимо от камеры. (Это проливает визуализацию из шага с маркировкой данных, но, как я на самом деле скрываются оси фигуры это не имеет значения в данном случае.)

Все, что вам нужно сделать, это:

m.actor.actor.rotate_y(desired_angle) 

... и вам хорошо идти.

2

Вам нужна математика. Хорошо, вот как это сделать с точки зрения кода, это не лучший код, но я хотел сделать его понятным. Я использую формулу Родригеса для вращения в 3d, чтобы добиться этого, az_new и el_new - ваши новые углы обзора. Измените значение тета, чтобы получить другой угол обзора в вашей системе отсчета, я использовал 45 градусов в коде ниже:

import numpy as np 
import math 

def rotation_matrix(axis, theta): 
    """ 
    Return the rotation matrix associated with counterclockwise rotation about 
    the given axis by theta radians. 
    """ 
    axis = np.asarray(axis) 
    theta = np.asarray(theta) 
    axis = axis/math.sqrt(np.dot(axis, axis)) 
    a = math.cos(theta/2.0) 
    b, c, d = -axis*math.sin(theta/2.0) 
    aa, bb, cc, dd = a*a, b*b, c*c, d*d 
    bc, ad, ac, ab, bd, cd = b*c, a*d, a*c, a*b, b*d, c*d 
    return np.array([[aa+bb-cc-dd, 2*(bc+ad), 2*(bd-ac)], 
        [2*(bc-ad), aa+cc-bb-dd, 2*(cd+ab)], 
        [2*(bd+ac), 2*(cd-ab), aa+dd-bb-cc]]) 


az = 90 
el = -75 

x = np.cos(np.deg2rad(el))*np.cos(np.deg2rad(az)) 
y = np.cos(np.deg2rad(el))*np.sin(np.deg2rad(az)) 
z = np.sin(np.deg2rad(el)) 

# So your viewing vector in x,y coordinates on unit sphere 
v = [x,y,z] 

# Since you want to rotate about the y axis from this viewing angle, we just increase the 
# elevation angle by 90 degrees to obtain our axis of rotation 

az2 = az 
el2 = el+90 

x = np.cos(np.deg2rad(el2))*np.cos(np.deg2rad(az2)) 
y = np.cos(np.deg2rad(el2))*np.sin(np.deg2rad(az2)) 
z = np.sin(np.deg2rad(el2)) 

axis = [x,y,z] 

# Now to rotate about the y axis from this viewing angle we use the rodrigues formula 
# We compute our new viewing vector, lets say we rotate by 45 degrees 
theta = 45 
newv = np.dot(rotation_matrix(axis,np.deg2rad(theta)), v) 

#Get azimuth and elevation for new viewing vector 
az_new = np.rad2deg(np.arctan(newv[1]/newv[0])) 
el_new = np.rad2deg(np.arcsin(newv[2])) 
+0

Большое спасибо, это выглядит полезным. Я попробую в понедельник, чтобы посмотреть, как это работает. – MassivePenguin

+0

Хммм, не совсем там (он вращается по неправильной оси). Возможно, мне придется попробовать совершенно другой подход ... – MassivePenguin

Смежные вопросы