2016-08-05 35 views
9

Ich zeichne ein 3D-Mesh mit Mayavis triangular_mesh Methode. Die Daten beschreiben eine menschliche Silhouette, die verdeckt im 3D-Raum liegt (so kann die cmap zur Bezeichnung der Entfernung von der Kamera verwendet werden).Mayavi: rotieren um die y-Achse

Hier ist der Code verwendet, um den Plot zu erzeugen (die Flächen und Ecken von einem externen Objekt kommen, und es gibt viel zu viele hier zu zeigen):

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]) 

ohne die Kamera zu bewegen, legt die Silhouette Gesicht -Nieder. Um das Modell frontal zu betrachten, verändere ich den Azimut und die Höhe der Kamera, um das Diagramm von oben nach unten zu betrachten. Dies zeigt die Silhouette wie vorgesehen.

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

Meine nächste Aufgabe ist es, eine Reihe von Bildern zu schaffen, wo die Kamera schwenkt um die Handlung, mit der Silhouette ausgehend nach rechts gerichtet, und endend mit nach links gegenüber.

Die Komplikation ist, dass, um die Colormap für die Tiefeninformationen zu erhalten, ich bereits den Azimut und die Höhe der Ansicht verschieben (wie im obigen Code gezeigt). Mayavi hat mehr Möglichkeiten, die Kamera als matplotlib zu bewegen, aber es scheint keine Möglichkeit zu geben, sich um die Y - Achse zu drehen, also muss ich wohl einige komplexe Berechnungen im Azimut und in der Höhe durchführen, um das zu erreichen Das gleiche Ergebnis - aber ich weiß nicht, wo ich anfangen soll (ich bin neu im 3D-Raum zu arbeiten, und mein Gehirn denkt noch nicht so).

Kann mir jemand in die richtige Richtung?

Antwort

1

Es stellt sich heraus, es ist ein bisschen eine Abhilfe für dieses.

Sie können die Aktoren unabhängig von der Kamera auf ihren Achsen drehen. (Dies wirft die Visualisierung aus Schritt mit den Beschriftungsdaten, aber wie ich eigentlich bin, die die Achsen der Figur versteckt ist es in diesem Fall nicht wichtig.)

Alles, was Sie tun müssen, ist:

m.actor.actor.rotate_y(desired_angle) 

... und du bist gut zu gehen.

2

Sie brauchen etwas Mathe hier. Ok, hier ist, wie es in Bezug auf Code zu tun ist, es ist nicht der beste Code, aber ich wollte es selbsterklärend machen. Ich benutze die Rodrigues-Formel für die Rotation in 3D, um dies zu erreichen, az_new und el_new sind deine neuen Betrachtungswinkel. Ändern Sie den Wert von theta einen anderen Blickwinkel in Ihrem Referenzrahmen zu bekommen, ich habe 45 Grad in den folgenden Code verwendet:

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

Vielen Dank, das sieht nützlich aus. Ich werde es am Montag ausprobieren, um zu sehen, wie es funktioniert. – MassivePenguin

+0

Hmmm, nicht ganz da (es dreht sich auf der falschen Achse). Ich muss vielleicht einen völlig anderen Ansatz ausprobieren ... – MassivePenguin