1
votes

So I have this code that produces the exact surface

f = function(x, y){
    z = ((x^2)+(3*y^2))*exp(-(x^2)-(y^2))
}
plot3d(f, col = colorRampPalette(c("blue", "white")), 
       xlab = "X", ylab = "Y", zlab = "Z", 
       xlim = c(-3, 3), ylim = c(-3, 3),
       aspect = c(1, 1, 0.5))

Giving the following plot: 3d exact plot Now I have some code that does a random walk metropolis algorithm to reproduce the above image. I think it works as if I do another plot of these calculated values I get the next image with 500 points. Here is the code

open3d()
plot3d(x0, y0, f(x0, y0), type = "p")

Which gives the following plot: enter image description here I know it's hard looking at this still image but being able to rotate the sampling is working.

Now here is my question: How can I use plot3d() so that I can have a surface that connects all these points and gives a more jagged representation of the exact plot? Or how can I have each point in the z axis as a bar from the xy plane? I just want something more 3 dimensional than points and I can't find how to do this.

Thanks for your help

3

3 Answers

2
votes

You can do this by triangulating the surface. You don't give us your actual data, but I can create some similar data using

f = function(x, y){
    z = ((x^2)+(3*y^2))*exp(-(x^2)-(y^2))
}
x <- runif(500, -3, 3)
y <- runif(500, -3, 3)
z <- f(x, y)

Then the plotting is done using the method in ?persp3d.deldir:

library(deldir)
library(rgl)
col <- colorRampPalette(c("blue", "white"))(20)[1 + round(19*(z - min(z))/diff(range(z)))]
dxyz <- deldir::deldir(x, y, z = z, suppressMsge = TRUE)
persp3d(dxyz, col = col, front = "lines", back = "lines")

This might need some cosmetic fixes, e.g.

aspect3d(2, 2, 1)

After some rotation, this gives me the following plot:

enter image description here

0
votes

I'm not sure to understand what you want. If my understanding is correct, here is a solution. Define a parametric representation of your surface:

fx <- function(u,v) u
fy <- function(u,v) v
fz <- function(u,v){
  ((u^2)+(3*v^2))*exp(-(u^2)-(v^2))
}

Let's say you have these points:

x0 <- seq(-3, 3, length.out = 20)
y0 <- seq(-3, 3, length.out = 20)

Then you can use the function parametric3d of the misc3d package, with the option fill=FALSE to get a wireframe:

library(misc3d)
parametric3d(fx, fy, fz, u=x0, v=y0, 
             color="blue", fill = FALSE)

enter image description here

Is it what you want?

To get some vertical bars, use the function segments3d of rgl:

i <- 8
bar <- rbind(c(x0[i],y0[i],0),c(x0[i],y0[i],f(x0[i],y0[i])))
segments3d(bar, color="red")
0
votes

Here is a plot with only 50 points using my original code.

Scatter graph of 50 points

When I then apply what was said by Stéphane Laurent I then get this plot which feels too accurate when given the actual points I have

wire plot

Perhaps you need to explain to me what is actually happening in the function parametric3d