1

I have a set of 3D coordinates (below - just for a single point, in 3D space):

x <- c(-521.531433, -521.511658, -521.515259, -521.518127, -521.563416, -521.558044, -521.571228, -521.607178, -521.631165, -521.659973)
y <- c(154.499557, 154.479568, 154.438705, 154.398682, 154.580688, 154.365189, 154.3564, 154.559189, 154.341309, 154.344223)
z <- c(864.379272, 864.354675, 864.365479, 864.363831, 864.495667, 864.35498, 864.358582, 864.50415, 864.35553, 864.359863)
xyz <- data.frame(x,y,z)

I need to make a time-series plot of this point with a 3D rendering (so I can rotate the plot, etc.). The plot will visualize a trajectory of the point above in time (for example in the form of solid line). I used 'rgl' package with plot3d method, but I can't make it to plot time-series (below, just plot a single point from first frame in time-series):

require(rgl)    
plot3d(xyz[1,1],xyz[1,2],xyz[1,3],axes=F,xlab="",ylab="",zlab="") 

I found this post, but it doesn't really deal with a real-time rendered 3D plots. I would appreciate any suggestions. Thank you.

Community
  • 1
  • 1
Geek On Acid
  • 6,330
  • 4
  • 44
  • 64
  • 1
    have you looked at `?movie3d` in the `rgl` package? I'm not quite sure what you mean by "real time" -- do you mean that the frame rate should exactly match the rate at which the data were collected (i.e. the trajectory moves ahead 1 second between points that were really collected 1 second apart), or just that you want to show a movie/animation of the data where movie time is proportional to data collection time (but not necessarily identical to it)? – Ben Bolker Nov 16 '11 at 14:19
  • Thank you Ben, the 'real-time' word is a bit confusing so I removed it from my question. I just meant that I want the 3D plot to be rendered so I can rotate it etc, not that I need to play any sequence. Sorry for the confusion. – Geek On Acid Nov 16 '11 at 14:31

3 Answers3

3

If you read help(plot3d) you can see how to draw lines:

require(rgl)    
plot3d(xyz$x,xyz$y,xyz$z,type="l")

Is that what you want?

Iterator
  • 20,250
  • 12
  • 75
  • 111
Spacedman
  • 92,590
  • 12
  • 140
  • 224
  • I am aware of this option but that's not what I'm looking for. The idea is that each row in 'xyz' defines a step in time and the x,y,z columns define a location of point for the specific time-step. So I need first step to be a point, and all the other steps to form a single line showing the location of this point in time. – Geek On Acid Nov 16 '11 at 14:25
  • Isn't the line drawn by type="l" a single line showing the location of the point in time? Is what you really want a moving dot? – Spacedman Nov 16 '11 at 14:36
  • Ok, the problem is that it doesn't seem to work for a large data-set, for example a motion capture data. I uploaded the sample [here](http://motioninsocial.com/files/Bob12.txt). It's a motion capture data from two actors. A single coordinate is coded by three columns (total 90 columns, 45 for a single actor, that is 15 points for each actor). I extract xyz into separate frames but I can't plot the 3D time series using type="l" or the 'ts' function you posted. – Geek On Acid Nov 16 '11 at 16:06
  • Okay, dont really know what you are doing with your data, but if I do bob=read.table("Bob12.txt");ts(bob[,1:3],0) I get a nice trail of the first 3 coordinates. The only problem I have is that you can't rotate the view while R is doing stuff or sleeping.. – Spacedman Nov 16 '11 at 16:35
  • Thank you - I need to play with your 'ts' function for a bit, but it is probably an answer to my question. To give you some more context - I have two actors standing in front of each other, interacting, for about 5 seconds. For each actor I have 15 markers describing location of their joint-centers. I want to see a time-series for each of the marker, but preserving the first frame as a set of points - so I can visualize the dynamics of movement. – Geek On Acid Nov 16 '11 at 16:56
3

How about this? It uses rgl.pop() to remove a point and a line and draw them as a trail - change the sleep argument to control the speed:

ts <- function(xyz,sleep=0.3){
  plot3d(xyz,type="n")
  n = nrow(xyz)
  p = points3d(xyz[1,])
  l = lines3d(xyz[1,])
  for(i in 2:n){
    Sys.sleep(sleep)
    rgl.pop("shapes",p)
    rgl.pop("shapes",l)
    p=points3d(xyz[i,])
    l=lines3d(xyz[1:i,])
  }
}
Iterator
  • 20,250
  • 12
  • 75
  • 111
Spacedman
  • 92,590
  • 12
  • 140
  • 224
2

The solution was simpler than I thought and the problem was that I didn't use as.matrix on my data. I was getting error (list) object cannot be coerced to type 'double' when I was simply trying to plot my entire dataset using plot3d (found a solution for this here). So, if you need to plot time-series of set of coordinates (in my case motion capture data of two actors) here is my complete solution (only works with the data set below!):

  • download example data set
  • read the above data into a table:

    data <- read.table("Bob12.txt",sep="\t")
    
  • extract XYZ coordinates into a separate matrixes:

    x <- as.matrix(subset(data,select=seq(1,88,3)))
    y <- as.matrix(subset(data,select=seq(2,89,3)))
    z <- as.matrix(subset(data,select=seq(3,90,3)))
    
  • plot the coordinates on a nice, 3D rendered plot using 'rgl' package:

    require(rgl)
    plot3d(x[1:nrow(x),],y[1:nrow(y),],z[1:nrow(z),],axes=F,xlab="",ylab="",zlab="")
    

You should get something like on the image below (but you can rotate it etc.) - hope you can recognise there are joint centers for people there. I still need to tweak it to make it visually better - to have first frame as a points (to clearly see actor's joints), then a visible break, and then the rest of frames as a lines.

Output of the above code from the above data

Community
  • 1
  • 1
Geek On Acid
  • 6,330
  • 4
  • 44
  • 64