6

Are there any way to plot a surface like ellipsoid with plotly 3D?

Currently only surfaces of the form z=f(x,y) are discussed in the docs. There is also Mesh 3D, but I found no examples for it. It seem to be possible to make a triangulation of ellipsoid manually and then use Mesh to get ellipsoid, but it looks a bit difficult for me. Are there any better way to do it?

Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
Ilya V. Schurov
  • 7,687
  • 2
  • 40
  • 78

3 Answers3

15

Okay, it is easier than I thought. There is alphahull option that asks plotly to calculate the corresponding triangulation automatically.

from plotly.offline import iplot, init_notebook_mode
from plotly.graph_objs import Mesh3d
import numpy as np

# some math: generate points on the surface of the ellipsoid

phi = np.linspace(0, 2*pi)
theta = np.linspace(-pi/2, pi/2)
phi, theta=np.meshgrid(phi, theta)

x = np.cos(theta) * np.sin(phi) * 3
y = np.cos(theta) * np.cos(phi) * 2
z = np.sin(theta)

# to use with Jupyter notebook

init_notebook_mode()

iplot([Mesh3d({
                'x': x.flatten(), 
                'y': y.flatten(), 
                'z': z.flatten(), 
                'alphahull': 0
})])

Ellipsoid

And this is R version:

library(pracma)
theta <- seq(-pi/2, pi/2, by=0.1)
phi <- seq(0, 2*pi, by=0.1)
mgrd <- meshgrid(phi, theta)
phi <- mgrd$X
theta <-  mgrd$Y
x <- cos(theta) * cos(phi) * 3
dim(x) <- NULL
y <- cos(theta) * sin(phi) * 2
dim(y) <- NULL
z <- sin(theta) * scale
dim(z) <- NULL

ell <- cbind(x, y, z)

ell <- setNames(ell, c('x', 'y', 'z'))

library(plotly)
p <- plot_ly(as.data.frame(ell), x=x, y=y, z=z, type='mesh3d', alphahull = 0)

p %>% layout(scene = list(aspectmode = 'data'))

EDIT: it is also possible to use type='surface' to produce parametric plots: in this case one have to provide two-dimensional x and y.

library(plotly)
library(pracma)
mgrd <- meshgrid(seq(-pi, pi, length.out = 100), seq(-pi/2, pi/2, length.out = 100))
U <- mgrd$X
V <- mgrd$Y
frame <- list(x=cos(V)*cos(U)*3, y=cos(V)*sin(U)*2, z=sin(V))
plot_ly(frame, type='surface', x=x, y=y, z=z, showlegend=F, showscale=F,
        colorscale=list(list(0, 'blue'), list(1, 'blue')))
U3.1415926
  • 812
  • 12
  • 30
Ilya V. Schurov
  • 7,687
  • 2
  • 40
  • 78
  • 1
    Whoa. I came back expecting this to be upvoted more than mine, but find that someone downvoted without explanation. – IRTFM Mar 06 '16 at 01:22
  • @42-, this is because your answer have a picture, and mine haven't. :) – Ilya V. Schurov Mar 06 '16 at 13:16
  • 1
    Your image is much nicer now. And your code looked to be at a "higher" level of abstraction. I'm glad your keeping your sense of humor. – IRTFM Mar 06 '16 at 15:41
5

Assuming the ellipsoid is given by the equation (X-c)'A(X-c) = r.

library(Rvcg)
sphr <- vcgSphere()
library(rgl)
ell <- scale3d(transform3d(sphr, chol(A)), r, r, r)
vs <- ell$vb[1:3,] + c
idx <- ell$it - 1
library(plotly)
p <- plot_ly(type="mesh3d",
  x = vs[1,], y = vs[2,], z = vs[3,],
  i = idx[1,], j = idx[2,], k = idx[3,],
  opacity = 0.3) 
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
2

Why not solve for z in this equation grabbed from the Mathematic item on ellipsoids:

enter image description here

require(plotly)
a=5; b=7; c=9
x=rep(seq(-10,10,by=1), each=21)
y=rep( seq(-10,10,by=1), times=21)
z <- c^2*sqrt(1-x^2/a^2-y^2/b^2)
#Warning message:
#In sqrt(1 - x^2/a^2 - y^2/b^2) : NaNs produced

 plot_ly(z = matrix(z,21,21), type = "surface")

enter image description here

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • 1
    Yeah, I thought about it, but I need not a half of ellipsoid, but the whole ellipsoid. I'm not sure, if it is possible to create two half-ellipsoid (probably yes) with sufrace plot, but I'm afraid it will not be so nice as Mesh 3d ellipsoid (surface plot may work strange where surface has almost vertical tangent plane). – Ilya V. Schurov Mar 06 '16 at 13:00
  • Your answer is clearly better. You should give yourself the checkmark. I wondered if there were a way to embed a plotly Mesh3d call into the R interface, but that's above my capabilities at the moment. – IRTFM Mar 06 '16 at 15:44
  • Finally, I found an answer which is a linear combination of yours and mine: use `type="surface"` but provide it two-dimensional `x` and `y` and get parametric plot in this way. (See update to my answer.) – Ilya V. Schurov Mar 06 '16 at 21:09
  • Strong work. In a couple of days, I'll hope if I can remember to come back and add a bounty so your work can be appropriately recognized. – IRTFM Mar 06 '16 at 21:57