2016-05-03 25 views
5

Sarebbe conveniente selezionare in modo interattivo un punto di vista decente utilizzando rgl e quindi adottare lo stesso orientamento in una trama 3D lattice. Ad esempio, dato il seguente grafico usando un punto di vista non informativo.replica di un punto di vista della rete in lattice

library(lattice) 
wireframe(volcano, screen = list(x=0, y=0, z=0)) 

enter image description here

Lo stesso può essere aperto in rgl da

library(rgl) 
persp3d(volcano) 
view3d(0, 0) 

enter image description here

interattivo è facile ruotare la trama di una vista informativo.

enter image description here

La matrice dando la corrente rgl punto di vista in può essere estratto con

p <- par3d() 
p$userMatrix 

Come può questa matrice essere convertiti in corrispondenti x, y, zscreen parametri di replicare la vista in lattice ?

UPDATE 1

Ho provato conversione 42 di seguito. Il codice mostra la trama rgl e il grafico reticolare corrispondente per riga. Se l'ho implementato correttamente (vedi il codice sotto), sembra che ci sia ancora un problema.

enter image description here

# convert rgl viewpoint into lattice 
# screen orientation 
rgl_to_lattice_viewpoint <- function() 
{ 
    p <- par3d() 
    rotm <- p$userMatrix 
    B = 360*atan(rotm[1,2]/rotm[2,2])/(2*pi) 
    P = 360*asin(-rotm[3,2])/(2*pi) 
    H = 360*atan(rotm[3,1]/rotm[3,3])/(2*pi) 
    list(x=-B, y=-P, z=-H) 
} 


# read and plot PNG image 
plot_png <- function(f) 
{ 
    img <- readPNG(f) 
    rimg <- as.raster(img)  # raster multilayer object 
    plot(NULL, xlim=c(0,1), ylim=c(0,1), xlab = "", ylab = "", 
     asp=1, frame=F, xaxt="n", yaxt="n") 
    rasterImage(rimg, 0, 0, 1, 1) 
} 


# create rgl snapshot with random rotation and 
# corresponding lattice wireframe plot 
lattice_plus_rgl_plot <- function() 
{ 
    # rgl plot random rotation 
    persp3d(volcano, col = "green3") 
    theta <- sample(-180:180, 1) 
    phi <- sample(-90:90, 1) 
    view3d(theta, phi, fov=40) 
    v <- rgl_to_lattice_viewpoint() 
    f <- tempfile(fileext = ".png") 
    rgl.snapshot(f) 
    rgl.close() 

    # lattice plot 
    f2 <- tempfile(fileext = ".png") 
    png(f2) 
    print(wireframe(volcano, screen = v)) 
    dev.off() 

    # plot both 
    plot_png(f) 
    plot_png(f2) 
} 

# CREATE SOME PLOTS 

library(rgl) 
library(lattice) 
library(png) 
par(mfrow=c(3,2), mar=c(0,0,0,0)) 
replicate(3, lattice_plus_rgl_plot()) 

risposta

1

ho usato la risposta a questa domanda per la conversione da una matrice di rotazione ad angoli: Conversion euler to matrix and matrix to euler. Ammetto di preoccuparmi di vedere un'altra risposta un po 'diversa qui: How to calculate the angle from Roational matrix. (Il mio algebra lineare non è sufficiente per determinare quale di questi è corretto.)

p <- par3d() 
rotm <- p$userMatrix 
B = 360*atan(rotm[1,2]/rotm[2,2])/(2*pi) 
P = 360*asin(-rotm[3,2])/(2*pi) 
H = 360*atan(rotm[3,1]/rotm[3,3])/(2*pi) 

> print(list(B,P,H)) 
[[1]] 
[1] 41.54071 

[[2]] 
[1] 40.28412 

[[3]] 
[1] 41.24902 

A quel punto avevo già ruotato l'RGL-oggetto a circa il "punto di osservazione" che aveva suggerito. Ho scoperto per sperimentazione che i valori negativi forniti alla chiamata wireframe hanno prodotto risultati apparentemente corretti. Gli "angoli di rotazione del visore" sono plausibilmente visti come negativi per "angoli di rotazione dell'oggetto".

png(); print(wireframe(volcano, screen = list(x=-B, y=-P, z=-H))); dev.off() 

enter image description here

C'è una funzione rotate.wireframe nel pacchetto TeachingDemos ma non gioca bene con in esecuzione contemporaneamente trame RGL. (Nessuna trama era evidente fino a quando non ho chiuso il dispositivo.) Sembrava anche un po 'buggy quando si eseguiva su un Mac (linea nera spessa sul tracciato del reticolo). Utilizza le funzionalità X11/XQuartz per gestire l'interazione tramite le funzioni tk/tcl e non sono stato in grado di riprodurre i grafici dagli angoli visualizzati. Guardando il codice non sono in grado di capire perché dovrebbe essere così. Ma il tuo chilometraggio può variare.

+0

Grazie! :) Ho modificato il mio post (UPDATE 1) dove ho provato la conversione suggerita. Sembra che ci sia un problema dato che non ho commesso errori. –

1

Questa versione della funzione utilizza conversioni dal pacchetto orientlib, e rende la matrice di rotazione argomento:

rgl_to_lattice_viewpoint <- function(rotm = par3d("userMatrix")) 
{ 
    e <- -orientlib::eulerzyx(orientlib::rotmatrix(rotm[1:3, 1:3]))@x*180/pi 
    list(z = e[1], y = e[2], x = e[3]) 
} 

noti che la z, y, x fine è essenziale.

Usandolo al posto della vostra funzione, ottengo questo output: rgl and lattice plots

Questi ottenere la giusta rotazione. Non so se è anche possibile ottenere la prospettiva in modo che corrisponda.

A cura di aggiungere: rgl versione 0.95.1468, finora disponibili solo su R-fucina, contiene una versione di questa funzione e uno per la grafica di base pure.