I have a large rivernetwork as a SpatialLines(DataFrame) and want to subset it so I get a SpatialLine with only the shortest/fastest path between two SpatialPoints(DataFrame) which propably need to be snapped onto the line first.
In the example Code, I want to get the closest line between the red dots, while moving on the lines. Also I want to move between the left red point and the right blue point, which needs to be snapped to the closest SpatialLine
library(sp)
x <- c(1,5,6,8)
y1 <- c(1,3,4,7)
y2 <- c(5,5,5,2)
L <- SpatialLines(list(Lines(Line(cbind(x,y1)), ID="a"),Lines(Line(cbind(x,y2)), ID="b")))
P <- SpatialPoints(data.frame(x=c(1,8),y=c(1,2)))
P_snap <- SpatialPoints(data.frame(x=c(8),y=c(1)))
plot(L)
points(P,col="red")
points(P_snap,col="blue")
Related
I have a raster stack made of 11 ascii files having temperature values of an area. Each file represents a different time point such as t2, t3,...,t12. I want to select one specific pixel from this area and I want to make a graph showing the changes of temperature values in time (from t2 to t12) of this pixel. I tried the following code:
> myfiles <- list.files(full.names = T)
> temp_files <- stack(myfiles)
> temp_values <- extract(temp_files, mypixel) # mypixel is defined by xyFromCell function
> plot(temp_values)
I check the values and it seemed right. But I will apply the same code for stacks with 500 layers and I cannot check each value in each layer so is this the right way to do that?
Here is a minimal, self-contained, reproducible example
library(raster)
r <- stack(system.file("external/rlogo.grd", package="raster"))
Now you can do things like
x <- 1:nlayers(r)
# select the cell you want
y <- r[4089]
# or
# extract(r, 4089)
And
plot(x, y)
So what you are doing appears to be correct.
I am having difficulty of producing X,Y coordinates of a circle and then drawing line segments to it. Basically what I want to do is draw 360 lines from the center of a circle to the outside of the circle in perfect spacing. This is how I am currently doing it but it is not working. If there is a different way to do this, that works great as well! Also I am hoping that degree 0 starts at the left side of the circle.
t <- seq(0,2*pi,length=360)
coords <- t(rbind( sin(t)*127.28125, cos(t)*127.28125))
plot(coords,type='n',xlim=c(-63.625625,63.625625),ylim=c(0,127.28125))
lines(coords)
deg=data.frame(coords[,1],coords[,2])
head(deg)
deg$count=1
deg$degree=1
for(i in 1:nrow(coords)){
if(deg$count[i]<=270){
deg$degree[i]=i-1+90-45
} else {
deg$degree[i]=i-1-270-45
}
}
names(deg)[1] <- "X"
names(deg)[2] <- "Y"
i=1
for(i in 1:19){
segments(0,0,deg$X[deg$degree==((5*(i-1)))],deg$Y[deg$degree==((5*(i-1)))])
cat(((5*(i-1))),'\t')
}
Update:
I am having some issues with where the lines get drawn. Basically as we go around the circle the errors get larger so when pi/2 radians happens and it is straight up, the value is slightly to the right of x=0. This may not be possible to get but thought I would ask to see if there was anyway to fix that! The 45 90 and 135 should all match on the lines.
How about this
th <- seq(0, 2*pi, length.out=360)
r <- 2
x <- r*cos(th)
y <- r*sin(th)
plot(x,y, type="n")
segments(0,0,x,y)
Basically i choose th and r in polar space and convert to Cartesian.
If you want to start with 0 on the left, use
x <- -r*cos(th)
instead.
I have a grid of rectangles, whose coordinates are stored in the variable say, 'gridPoints' as shown below:
gridData.Grid=GridTopology(c(min(data$LATITUDE),min(data$LONGITUDE)),c(0.005,0.005),c(32,32));
gridPoints = as.data.frame(coordinates(gridData.Grid))[1:1000,];
names(gridPoints) = c("LATITUDE","LONGITUDE");
plot(gridPoints,col=4);
points(data,col=2);
When plotted, these are the black points in the image,
Now, I have another data set of points called say , 'data', which when plotted are the blue points above.
I would want a count of how many blue points fall within each rectangle in the grid. Each rectangle can be represented by the center of the rectangle, along with the corresponding count of blue points within it in the output. Also, if the blue point lies on any of the sides of the rectangle, it can be considered as lying within the rectangle while making the count. The plot has the blue and black points looking like circles, but they are just standard points/coordinates and hence, much smaller than the circles. In a special case, the rectangle can also be a square.
Try this,
x <- seq(0,10,by=2)
y <- seq(0, 30, by=10)
grid <- expand.grid(x, y)
N <- 100
points <- cbind(runif(N, 0, 10), runif(N, 0, 30))
plot(grid, t="n", xaxs="i", yaxs="i")
points(points, col="blue", pch="+")
abline(v=x, h=y)
binxy <- data.frame(x=findInterval(points[,1], x),
y=findInterval(points[,2], y))
(results <- table(binxy))
d <- as.data.frame.table(results)
xx <- x[-length(x)] + 0.5*diff(x)
d$x <- xx[d$x]
yy <- y[-length(y)] + 0.5*diff(y)
d$y <- yy[d$y]
with(d, text(x, y, label=Freq))
A more general approach (may be overkill for this case, but if you generalize to arbitrary polygons it will still work) is to use the over function in the sp package. This will find which polygon each point is contained in (then you can count them up).
You will need to do some conversions up front (to spatial objects) but this method will work with more complicated polygons than rectangles.
If all the rectangles are exactly the same size, then you could use k nearest neighbor techniques using the centers of the rectangles, see the knn and knn1 functions in the class package.
I wanted to draw 2 equilateral triangles. One upside down and the other upside up.
Here is my code:
ord<-c(1,3,5)
ord1<-c(2,4,6)
x1<-x[ord]
y1<-y[ord]
x2<-x[ord1]
y2<-y[ord1]
lines(x1,y1,col="blue")
lines(x2,y2,col="blue")
However, I can't get the figure to make complete triangle. I only get 2 sides of each triangle. What am I doing wrong?
lines will draw from the first coord to the second, second to third, etc. If you want it to come back to the first point, just duplicate it at the end:
ord <- c(1,3,5,1)
ord1 <- c(2,4,6,2)
to get it come back to the first point.
Using the fact that the third point is halfway between the first and the second, and the angle is pi/3, you can do this for example:
angle=pi/3
x <- c(0,0.5,0.5*cos(angle),0)
y <- c(0,0,sin(angle),0)
y1 <- c(0,0,-sin(angle),0)
plot(-1:1,-1:1,type='n')
polygon(x=x,y=y,col='red') ## you can replace polygon by lines here
polygon(x=x,y=y1,col='green')
I have a vector of coordinates where each row designates the centre of a circle:
x <- runif(5,0,2)
y <- runif(5,0,2)
As you can see the circles centres are all found within the square (0,2).
Each circle has a radius 0.2. I want to randomly shift the centre of the circles within the bounds of the original circle. I figured I could do this:
radii <- (sample(20,5,replace=TRUE))/100
angles <- sample(360,5,replace=TRUE)
newx <- x + radii*(cos(angles))
newy <- y + radii*(sin(angles))
However, I realise that doing this I could technically get circle centres that fall outside of the square (0,2). I could try and write a loop that rejects newx and newy values that are negative. But have to do this for 10s of thousands of rows and worried about the speed of this. Is it possible to run this conditional coordinate shift without resorting to a loop?
My rule set is as follows:
pick a new circle centre for each centre.
The new centres must fall within the area of each circle (radius 0.2 distance from the original centre)
The new centres must lie within the original square.
If a centre meets the border of the circle it should be reflected as of the law of reflection (be reflected the remaining length of the random radius distance selected)
Something like this:
#lets do only one point first
x <- runif(1,0,2)
y <- runif(1,0,2)
randomwalk <- function (pos) {
x <- pos[1]
y <- pos[2]
radius <- (sample(20,1,replace=TRUE))/100
angle <- sample(360,1,replace=TRUE)
newx <- x + radius*(cos(angle))
newy <- y + radius*(sin(angle))
if (newy > 2) { #check the geometric calculations
r2 <- (2-y)/sin(angle)
hitx <- x + r2*(cos(angle))
hity <- 2
newx <- hitx + (radius-r2)*sin(angle)
newy <- hity - (radius-r2)*cos(angle)
}
#implement other borders yourself
#and include a check, which border is hit first
#and include the possibility for multiple hits
#(e.g., left border and then top border)
cbind(newx,newy)
}
resx <- vector(50,mode="numeric")
resy <- vector(50,mode="numeric")
res <- cbind(resx,resy)
res[1,] <- cbind(x,y)
for (i in 2:50) {
res[i,] <- randomwalk(res[i-1,])
}
I suspect this still contains some geometric errors, but don't have time to check.
The functions inpip and inout from package splancs is quite useful; they can be used to check if points fall inside a polygon. You just need a matrix with 2 columns which represents any polygon (such as a square). This functions are made to be fast, using C and Fortran programs.
If your square is:
square <- cbind(c(0, 10, 10, 0), c(0, 0, 10, 10)) # In case side = 10
Then create all the new centers (I suggest using runif instead of sample for the radii and angle, but that's up to you). Then check if those centers fall inside the square with one line:
inside <- inout(newCenters, square)
newCenters <- newCenters[inside]
And afterwards you should do all the necessary steps to recreate the newCenters that where selected out, as many times as needed until they fall inside the square. Note that this needs a while loop (or equivalent).
Note also that in the same package (splancs) there is this function csr that create random points inside a polygon. So in principle you could cut a piece of every circumference that falls outside the square and then use the resulting polygons (the cut circles) as input to this function. This can become slow because you have to use a loop (or a lapply maybe) for all cut circles.
As a last idea, maybe you can combine the two strategies. First use your initial idea to all circumferences that fall completely inside the square (or equivalently, all the centers that are at a distance of 2 or more from the perimeter). Then use the csr function for all the rest of the circles.
Hope this helps!