Play3d in RGL package - r

I am working on a project using the RGL package in R programming. I would love if someone could help me with the play3d function of the same.
Here is what I plan to do. I have a polygon3d(x,y,z) that plots a polygon on the output window and now I would want to translate it with some value at each iteration, say by 10 units for 5 rounds.
I researched but all the available resources are about rotation of the polygon for t-duration. Example of such a case is:
M <- par3d("userMatrix")
play3d(
par3dinterp(userMatrix=list(M,rotate3d(M, angle=pi, x=1 ,y=0, z=0))),
duration=10
)
The above code rotates my polygon along x-axis for 10seconds and stops.
I want to translate my polygon for 10 seconds with some given parameters specifying how much to translate at each second.
My polygon is basically a plus sign(representing a quadcopter) and I want to show the motion as if it is elevating from the ground(x-y axis) into the air(z-axis).
Any help will be deeply appreciated.
Thanks all

You need to use the transpose of a translation matrix to do this. For example, to translate by (x, y, z), use
M <- par3d("userMatrix")
play3d(
par3dinterp(userMatrix=list(M, M %*% t(translationMatrix(x, y, z)))),
duration=10
)
This is done in the ?rgl.setMouseCallbacks example.
Edited to add x, y, z values to answer question below.

Related

Rasterize SpatVect (points) with buffer around SpatRaster

I have a SpatVect consisting of points and I want to rasterize them into a SpatRaster with a given resolution. Is there a way of specifying a function taking in the points that are within a buffer of each raster cell?
Many thanks
Joao
-- Update --
Maybe a figure would help understand what I'm after with my question. The red square will have to be run over the center of each pixel to calculate some statistics using the ovelaying points. Apologies for the clumsy question, but I hope the figure is clear enough...
terra version 1.6-28 supports rasterization of points with a rectangular moving window.
Example data
library(terra)
#terra 1.6.33
r <- rast(ncol=100, nrow=100, crs="local", xmin=0, xmax=50, ymin=0, ymax=50)
set.seed(100)
x <- runif(50, 5, 45)
y <- runif(50, 5, 45)
z <- sample(50)
v <- vect(data.frame(x,y,z), geom=c("x", "y"))
Solution
r1 <- rasterizeWin(v, r, field="z", fun="count", pars=10, win="rectangle")
plot(r1)
points(x, y)
You can change fun to another function that works for you, and you can change the size of the moving window with pars.
Instead of a rectangle, you can also use a circle or an ellipse. The border of a circular window is equidistant from the center of the cells. In contrast, the border of rectangles are at a constant distance from the border of the grid cells in most directions (not at the corners). Here is an example.
r2 <- rasterizeWin(v, r, field="z", fun="count", pars=5.25, win="circle")
plot(r2)
You can also use buffers around each cell to get a window that is truly equidistant from each cell border.
r3 <- rasterizeWin(v, r, field="z", fun=length, pars=5, win="buf")
plot(r3)
In this case, because the buffer size is large relative to the cell size, the result is very similar to what you get when using a circular window. Using "circle" should be the fastest, and using "buffer" should be the slowest in most cases. The function should now in all cases be memory-safe, except, perhaps when using very large buffers (more could be done if need be).
Version 1.6-28 is currently the development version. You can install it with
install.packages('terra', repos='https://rspatial.r-universe.dev')
The approach you take seems to depend on what result you're looking for from the above and the relationship they have with each other.
library(terra)
`terra::buffer(` # both SpatVectx/SpatRastery, to distance in 'm'
`terra::buffer(` # that is meaningful
#take Rasty to SpatVecty
`terra::as.polygons(`, #then
`z<-terra::intersection(SpatVectx, SpatVecty)`
then back to SpatRastz? terra::mask or crop, might also be useful, again depending on where things are going next.

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 to intersect an interpolated surface z=f(x,y) with z=z0 in R

I found some posts and discussions about the above, but I'm not sure... could someone please check if I am doing anything wrong?
I have a set of N points of the form (x,y,z). The x and y coordinates are independent variables that I choose, and z is the output of a rather complicated (and of course non-analytical) function that uses x and y as input.
My aim is to find a set of values of (x,y) where z=z0.
I looked up this kind of problem in R-related forums, and it appears that I need to interpolate the points first, perhaps using a package like akima or fields.
However, it is less clear to me: 1) if that is necessary, or the basic R functions that do the same are sufficiently good; 2) how I should use the interpolated surface to generate a correct matrix of the desired (x,y,z=z0) points.
E.g. this post seems somewhat related to the problem I am describing, but it looks extremely complicated to me, so I am wondering whether my simpler approach is correct.
Please see below some example code (not the original one, as I said the generating function for z is very complicated).
I would appreciate if you could please comment / let me know if this approach is correct / suggest a better one if applicable.
df <- merge(data.frame(x=seq(0,50,by=5)),data.frame(y=seq(0,12,by=1)),all=TRUE)
df["z"] <- (df$y)*(df$x)^2
ta <- xtabs(z~x+y,df)
contour(ta,nlevels=20)
contour(ta,levels=c(1000))
#why are the x and y axes [0,1] instead of showing the original values?
#and how accurate is the algorithm that draws the contour?
li2 <- as.data.frame(contourLines(ta,levels=c(1000)))
#this extracts the contour data, but all (x,y) values are wrong
require(akima)
s <- interp(df$x,df$y,df$z)
contour(s,levels=c(1000))
li <- as.data.frame(contourLines(s,levels=c(1000)))
#at least now the axis values are in the right range; but are they correct?
require(fields)
image.plot(s)
fancier, but same problem - are the values correct? better than the akima ones?

kernel density function in R gives unequal x and y resolution

I hope you can help me with a problem that I've had for a while now. I need to make a bias file for MaxEnt, for which I have used this tutorial: https://scottrinnan.wordpress.com/2015/08/31/how-to-construct-a-bias-file-with-r-for-use-in-maxent-modeling/ and altered it to my own situation. However, I'm stuck now...
I need to use the kde2d function to create a 2d kernel density estimation and then turn that into a raster. However, the raster that is created has a different resolution for x and y. This is a problem, since I have to use it in MaxEnt which won't accept unequal x and y resolutions.
This is what I did:
biasraster <- raster("file.tif") #load raster with all the occurrences
presences <-which(values(biasraster)==1)
pres.locs<- coordinates(biasraster)[presences,]
dens <-kde2d(pres.locs[,1],pres.locs[,2],n=c(nrow(biasraster),ncol(biasraster))) #2d kernel density function on the biasraster
dens.ras<-raster(dens) #create raster from kde2d function
The original resolution of the biasraster is 0.00833333 for both x and y, but the resolution for dens.ras has changed to 0.0104052, 0.00833333 (x,y) (so the y resolution is the correct one).
As can probably be seen from the question, I am a total noob when it comes to coding (in r). I've been trying to figure out what to do for about a week now but I can't find any answers that seem to work, so I hope someone here can help me.
I had the same problem. I only could solve it using:
dens.ras <- resample(dens.ras, climdat, method="bilinear") #make bias file in the same resolution of climdat
but additionaly, I need also cut dens.ras.
densmod<-crop(dens.ras,extent(climdat))
With these additional steps, my bias file worked well.

R Find the point of intersection of two lines connecting 4 coordinates

I apologize in advance if my code looks very amateurish.
I'm trying to assign quadrants to 4 measurement stations approximately located on the edges of a town.
I have the coordinates of these 4 stations:
a <- c(13.2975,52.6556)
b <- c(14.0083,52.5583)
c <- c(13.3722,52.3997)
d <- c(12.7417,52.6917)
Now my idea was to create lines connecting the north-south and east-west stations:
line.1 <- matrix(c(d[1],b[1],d[2],b[2]),ncol=2)
line.2 <- matrix(c(a[1],c[1],a[2],c[2]),ncol=2)
Plotting all the stations the connecting lines looks allright, however not very helpful for analyzing it on a computer.
So I calculated the eucledian vectors for the two lines:
vec.1 <- as.vector(c((b[1]-d[1]),(b[2]-d[2])))
vec.2 <- as.vector(c((c[1]-a[1]),(c[2]-a[2])))
which allowed me to calculate the angle between the two lines in degrees:
alpha <- acos((vec.1%*%vec.2) / (sqrt(vec.1[1]^2+vec.1[2]^2)*
sqrt(vec.2[1]^2+vec.2[2]^2)))) * 180/pi
The angle I get for alpha is 67.7146°. This looks fairly good. From this angle I can easily calculate the other 3 angles of the intersection, however I need values relative to the grid so I can assign values from 0°-360° for the wind directions.
Now my next planned step was to find the point where the two lines intersect, add a horizontal and vertical abline through that point and then calculate the angle relative to the grid. However I can't find a proper example that does that and I don't think I have a nice linear equation system I could solve.
Is my code way off? Or maybe anyone knows of a package which could help me? It feels like my whole approach is a bit wrong.
Okay I managed to calculate the intersection point, using line equations. Here is how.
The basic equation for two points is like this:
y - y_1 = (y_2-y_1/x_2-x_1) * (x-x_1)
If you make one for each of the two lines, you can just substitute the fractions.
k.1 <- ((c[2]-a[2])/(c[1]-a[1]))
k.2 <- ((b[2]-d[2])/(b[1]-d[1]))
Reshaping the two functions you get a final form for y:
y <- (((-k.1/k.2)*d[2]+k.1*d[1]-k.1*c[1]+d[2])/(1-k.1/k.2))
This one you can now use to calculate the x-value:
x <- ((y-d[2])+d[1]*k.2)/k.2
In my case I get
y = 52.62319
x = 13.3922
I'm starting to really enjoy this program!
Wikipedia has a good article on finding the intersection between two line segments with an explicit formula. However, you don't need to know the point of intersection to calculate the angle to the grid (or axes of coordinate system.) Just compute the angles from your vec.1 and vec.2 to the basis vectors:
e1 <- c(1, 0)
e2 <- c(0, 1)
as you have done.

Resources