library(pracma)
phi <- seq(-pi/2, pi/2, by=0.1)
theta <- seq(0, 2*pi, by=0.1)
mgrd <- meshgrid(phi, theta)
phi <- mgrd$X
theta <- mgrd$Y
scale = qnorm(1-0.01/2)
x <- cos(phi) * cos(theta) * scale
dim(x) <- NULL
y <- cos(phi) * sin(theta) * scale
dim(y) <- NULL
z <- sin(phi) * scale
dim(z) <- NULL
sphere = as.matrix(rbind(x, y, z))
N <- 100
x <- rnorm(N)
y <- rnorm(N)
z <- rnorm(N)
C <- t(matrix(c(4, 0, 0, 0, 2, 0, 0, 0, 1), nrow = 3))
theta <- pi/4
phi <- pi/6
rot1 <- t(matrix(c(sin(theta), cos(theta), 0,
cos(theta), -sin(theta), 0,
0, 0, 1), nrow=3))
rot2 <- t(matrix(c(1, 0, 0,
0, sin(phi), cos(phi),
0, cos(phi), -sin(phi)),nrow=3))
rot = rot1 %*% rot2
C <- rot %*% C
points <- setNames(data.frame(t(C %*% as.matrix(rbind(x, y, z)))), c('x', 'y', 'z'))
ell <- setNames(data.frame(t(C %*% sphere)), c('x', 'y', 'z'))
print(points[1:5,])
## x y z
## 1 0.6342832 3.3748724 -0.03145166
## 2 -1.7891032 -2.3421015 0.52137608
## 3 1.2805058 0.6694286 1.17129645
## 4 5.6448206 4.4006883 -0.15911536
## 5 2.2407650 1.5251863 -0.62399069
library(plotly)
## Loading required package: ggplot2
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:graphics':
##
## layout
p <- plot_ly(points, x = x, y = y, z = z, type = "scatter3d", mode = "markers") %>% layout(scene = list(aspectmode = 'data'))
p
p <- add_trace(p, data = ell, x=x, y=y, z=z, type='mesh3d', alphahull = 0, opacity=0.4, hoverinfo='none')
p
arrow_profile <- function(len, width=0.2, headlength=2, headwidth=0.5, steps=50) {
X <- c(-len, seq(-len, len-headlength, length.out = steps %/% 2),
len-headlength,
seq(len-headlength+1E-5, len, length.out = steps %/% 2))
Y <- c(0, rep(width, length(X)-1))
for (i in 1:length(X)) {
if (X[i] > len-headlength) {
Y[i] = (len - X[i])*headwidth/(headlength)
}
}
list(X=X, Y=Y)
}
rotate <- function(profile, thetasteps=50) {
X <- profile$X
R <- profile$Y
Theta <- seq(0, 2*pi+2*pi/thetasteps, length.out = thetasteps)
mgrd <- meshgrid(X, Theta)
X <- mgrd$X
R <- meshgrid(R, Theta)$X
Theta <- mgrd$Y
Y <- R*cos(Theta)
Z <- R*sin(Theta)
list(x=X, y=Y, z=Z)
}
apply_matrix <- function(C, points) {
x <- points$x
y <- points$y
z <- points$z
n <- nrow(x)
m <- ncol(x)
outx <- matrix(rep(0, n*m), nrow = n)
outy <- matrix(rep(0, n*m), nrow = n)
outz <- matrix(rep(0, n*m), nrow = n)
for (i in 1:nrow(x)) {
for (j in 1:ncol(x)) {
out <- C %*% c(x[i, j], y[i, j], z[i, j])
outx[i,j] <- out[1,]
outy[i,j] <- out[2,]
outz[i,j] <- out[3,]
}
}
list(x=outx,y=outy,z=outz)
}
p <- add_trace(p, data = apply_matrix(rot,rotate(arrow_profile(14))), x=x, y=y, z=z, type='surface', hoverinfo='none', showscale=F, colorscale=list(list(0, "#009E73"), list(1, "#009E73")))
p
scale = 2
project_along_PC1 <- list(camera=list(eye=list(x=rot[1,1]*scale, y=rot[2,1]*scale, z=rot[3,1]*scale)))
p %>% layout(scene=project_along_PC1)
p
p %>% layout(
scene=list(
camera=list(
eye=list(
x=rot[1,3]*scale,
y=rot[2,3]*scale,
z=rot[3,3]*scale),
up=list(
x=rot[1,2],
y=rot[2,2],
z=rot[3,2])
)
)
)