Make a 3D rendered plot of time-series - r

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.

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?

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,])
}
}

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.

Related

R: creating DEM of an imaginary map from png

I have drawn an imaginary map for fun, and I thought it would be even more fun to make a DEM for the imaginary country using R, just to add to the visualization. :)
Basically, I now have a png with the outline of the country. Just only with a black border, the rest is left white.
My plan was to create a raster from it, so I could eventually add values to every pixel in the map. Since it's a imaginary map, it doesn't have a coordinate system. I just set the extent as it is as png:
drawing <- raster('drawing.png')
extent(drawing) <- c(0, 388, 0, 348)
Then I create a dataframe with the points of which eventually the DEM is calculated from. Basically, I just randomly select pixel locations within the country (name them x and y) and assign a random value as height. For this I use a simple excel sheet:
samples <- read_excel('samples.xlsx')
coordinates(samples) <- ~x+y
spatlocations <- SpatialPoints(samples)
vectlocations <- vect(samples)
Then, I thought, I could create a map using Inverse Distance Weighting (IDW), just to get a nice smooth gradient looking map. So it would possibly something like this:
result <- idw(unsampled, samples)
However, I fail to do this. I for example don't really know how to exactly work with the raster I created from the png, and the same for the sample points.
As you maybe can see, I am what you could consider a beginner :).
Is this possible at all? Is this methodology correct? How can I achieve such a map? Thanks in advance!

Is it possible to add marks to a 3D point pattern using SpatStat in Rstudio?

I am using spatstat software to analyse the spatial relationship between cells. I have used this in the past for 2D and it was fine. I am now using it for 3D analysis from confocal images.
My problem is that I am unable to plot the resultant point pattern with different marks. I am able to assign the marks (cell type) to each point and plot the 3D point pattern. However the marks do not appear on the plot as different characters.
Series6 <-pp3(Series6[,5], Series6[,6],Series6[,7],box3(c(0,775),c(0,775),c(0,30)), marks = Series6[,8])
The resultant plot: 3D Plot
I have tried it with 2D point patterns and it works fine displaying a different character for each mark. This makes me think that the marks feature isn't compatible with 3D point patterns. I would be grateful if anyone had any tips.
A three dimensional point pattern (class pp3) can have marks. Your code has successfully assigned marks to the points. You could check this by typing head(as.data.frame(Series6)) which would show the coordinates and marks of the first few points.
The problem is that the plot method, plot.pp3, does not display the marks. This feature is not yet implemented.
I will take this question as a feature request for spatstat.
In the meantime, you can get the desired effect by splitting the point pattern into subsets with different marks (assuming the marks are categorical) and plotting each subset in turn. Here is a function to do that:
plotbymark <- function(X, cols=NULL, chars=NULL, main="") {
require(spatstat)
stopifnot(is.pp3(X))
stopifnot(is.multitype(X))
Y <- split(X, un=TRUE)
m <- length(Y)
mm <- seq_len(m)
if(is.null(cols)) cols <- mm
if(is.null(chars)) chars <- mm
for(i in mm) {
plot(Y[[i]], col=cols[i], pch=chars[i], add=(i > 1), main=main)
}
explain <- data.frame(type=names(Y), col=cols, pch=chars)
return(invisible(explain))
}

Strange object in vector3d() graphic when using matlib + rgl

I'm trying to plot 3-dimensional vectors (x, y, z coordinates) onto a 3D coordinate system in R like in the picture below. Ideally, I would then like to construct 3d kernel density plots, also like in the image below.
Ideal result of vector plot and 3d kernel density plot
I have a matrix containing ~100 rows and one column for each coordinate (x, y , z). Initially, I tried arrow3D() from the plot3D package but I find the perspective to be sub-par, it's rather difficult to discern directions of the arrows from one perspective in the final plot. Next I tried the rgl package which gives me interactivity - great. Minimal working example:
library(rgl)
library(matlib)
data2 <- data.frame(replicate(6,rnorm(100))) #sample data set for minimum working example
colnames(data2) <- c("x_target", "y_target", "z_target", "x_start", "y_start", "z_start")
x1 <- data2$x_target - data2$x_start
y1 <- data2$y_target - data2$y_start
z1 <- data2$z_target - data2$z_start
vec <- (diag(6,3)) # coordinates for x, y and z axis
rownames(vec) <- c("X", "Y", "Z") # labels for x, y and z axis
z <- as.matrix((data.frame(x=x1, y=y1, z=z1)))
open3d()
vectors3d(vec, color=c(rep("black",3)), lwd=2, radius=1/25)
vectors3d(X=z, headlength=1/25)
(due to the random numbers generator the strange looking rods appear at different coordinates, not exactly like in the image i link to below)
The result of the code above is a version of the image link below. One set of coordinates produces a very strange looking more like rod object which is far longer then the coordinates would produce. If I plot the vectors individually, no such object is created. Anyone have any ideas why this happens? Also, if anyone has a tool (doesn't have to be R), that can create a 3D vector plot like in the first image, I'd be grateful. I find it to be very complicated in R, but I'm definitely a beginner.
Strange object to the right (long red rod that doesn't look like an arrow at all)
Thank you!
This is due to a bug in the matlib package, fixed in verson 0.9.2 of that package. I think you need to install it from Github instead of CRAN to get the bug fix:
devtools::install_github("friendly/matlib")
BTW, if you are using random numbers in a reproducible example, you can make it perfectly reproducible by something like
set.seed(123)
at the start (or some number other than 123). I saw reproducible problems with your example for set.seed(4).

How can I get the area of each Voronoi Polygon in R?

I have a set of coordinates X and Y for my points and used the deldir to create determine and plot the Voronoi Polygons. (I've used this tutorial here)
This is my plot: (sorry that its so small, but you get the idea).
I need to determine the area of each polygon. How can I do that?
I looked up in the deldirpackage page and couldnt find anything related to the Voronoi polygons, only about other
Based on the reference manual (https://cran.r-project.org/web/packages/deldir/index.html), the output of the deldir function is a list. One of the list element, summary, is a data frame, which contains a column called dir.area. This is the the area of the Dirichlet tile surrounding the point, which could be what you are looking for.
Below I am using the example from the reference manual. Use $ to access the summary data frame.
library(deldir)
x <- c(2.3,3.0,7.0,1.0,3.0,8.0)
y <- c(2.3,3.0,2.0,5.0,8.0,9.0)
dxy1 <- deldir(x,y)
dxy1$summary

polar image plot, how to do it with R?

I cannot find a straightforward way to make a nice image plot in R, but in polar coordinates. I'm basically attempting to find a R equivalent for the 'polarplot3d' function in MATLAB. I've been playing around with ggplot2 package but without much luck. Am I missing a package that contains functionality for what I'm attempting? thanks in advance for any pointers.
Ok, I'm trying to be more clear about what I'm trying to do. Lets say I want to define a polar coordinate grid, increments in the radial direction are 50m and 2.5 degrees in theta. This should look like a dartboard.
My data (r and angle in below code) are correspond to a radial distance measure and an angle. My desired z-value is the counts of a bivariate histogram between r and angle within the increments described above defining the grid.
My data is like the following:
# synthetic data for angle and distance #
angle <- rnorm(500,mean=90,sd=15)
r <- rnorm(500,mean=700,sd=200)
# bivariate histogram #
observations <- table(cut(angle,breaks=c(seq(0,360,by=2.5))),cut(r,breaks=c(seq(0,1400,by=50))))
# the 'z' data are in observations for each bin of bivariate histogram #
# hot to plot a polar coord image? #
It's very slow to render on my system, but
library(reshape2)
library(ggplot2)
mm <- melt(counts)
ggplot(mm,aes(Var1,Var2,fill=value))+geom_tile()+coord_polar()
ggsave("polar1.png")
appears to work.
I think the following could work. Use mapproject() from the maproj library to transform my xy coordinates acording to a polar projection (or another), Then use as.image() (from fields package) function to build a image object from my new coordiantes and my Z values. Eventually use image.plot().
library("mapproj")
xyProj <- mapproject(x, y, projection="conic", parameters=-90)
library("fields")
im <- as.image(z, x=xyProj)
image.plot(im)

Resources