Hey all, I have a challenge that I'm fairly stuck on. There is likely a
fast solution, but I don't know what it is. I'm trying to create a fast
function to calculate exposure to wind based on topography (similar to
Boose et al.). It's conceptually simple, in that it's similar to a
viewshed - if you're sheltered from a higher elevation down wind, you
aren't exposed. But, the wind is allowed to "bend" down at a given angle.
So I need to calculate exposure to wind that bends down a bit (like a
viewshed, but the light can bend down a tad). That bending distance is the
"threshold."
I've got a function that works, but it's very slow. I know why - it's slow
because it's running cell by cell. But I'm at a loss as to how to
calculate exposure for the whole raster at a time - mainly because of that
bending.
I've tried translating the raster via the shift function, but haven't
gotten that to work. Currently, I have a function to extract the
elevations over a line at a given angle/distance. Then I calculate the
angles, and if any angle is larger than the threshold angle, the point is
sheltered. If not angles are less, it's not.
There must be a faster way, however. I imagine there's a clever way to
take advantage of rasters decent computing speed, but my function is the
bottleneck. Any thoughts? I've tried working on this for a while, and I'm
at the point where it's just fast enough for what I need, if I run it over
the weekend (64bit, 8mb ram, i7 intel). Code is pasted below. I've put
off posting this here hoping to figure it out myself, but I'm not making a
lot of headway, and it's easier to explain by posting code than anything
else.
Thanks in advance!
#Code#
###################
require(rgeos)
library(raster)
library(rgdal)
#parameters for later
angle.list <- c(90,180) #180is south
dem <- dem #any dem in UTM coordinates
#function to extract location at given angle and distance. 0 is due
north. angle in degrees. I found this online somewhere- would love to
attribute it to the right person but don't remember where I found it.
####
retPoCordinates <- function(center,angle,distance){
angle <- (angle+90)*.0174532925 #convert to radians.
x <- round(center@coords[1,1] + distance * cos(angle),0)
y <- round(center@coords[1,2] + distance * sin(angle),0)
result <- as.data.frame(cbind(x,y));names(result) <- c("x","y")
return(result)
}
################
#Main function
#
################
out <- function(dem, deflect, angle.list,max.dist) {
#note that the dem raster must be in UTM
#direction
num.angle <- length(angle.list)
start.ang <- 1
while (start.ang <= num.angle) { #for multiple angles,
single deflection degree
angle <- angle.list[start.ang]
num.dist <- round(max.dist/res(dem)[1]/2) #number of
distances to check, basically goes every other cell for speed.
distance <- seq(res(dem)[1],max.dist,length.out=num.dist)
#temp storage
dist.store <- matrix(nrow=length(distance),ncol=1)
output <- dem*0
output <- as.matrix(output)
output <- as.vector(output)
#initial elevation vector
temp.elev <- extract(dem, 1:ncell(dem), df = TRUE)
temp.elev[is.na(temp.elev)==T] <- 0
#initial xy coordinates vector
cells <- temp.elev$ID
cells <- temp.elev$ID[which(temp.elev[,2]>0)]
coords <- xyFromCell(dem,cells,spatial=T)
#for each cell in matrix
index <- length(cells)
s <- 1
d <- res(dem)[1]
while (s <= index) { #bottleneck.
i <- cells[s]
#remove NA
g.elev <- ifelse(is.na(temp.elev[i,2]),0,temp.elev[i,2])
#if g.elev = 0,
if (g.elev == 0) {
temp.out <- -1
} else {
#calculate location at distance
out <- retPoCordinates(coords[s],angle,distance)
out <- SpatialPoints(out,proj4string=CRS(projection(dem)))
comp.elev <- extract(dem,out)
diff <- comp.elev - g.elev
temp <- diff/distance
ang <- atan(temp)*57.2958
#elminate NA's
ang <- ifelse(is.na(ang)==T,-100,ang)
#testing
#print(ang)
#plot(out,add=T)
temp.out <- ifelse(max(ang)>deflect,0,1)
}
output[i] <- temp.out
print(s/length(cells))
s <- s+1
}
#save output
t <- matrix(output,nrow=nrow(dem),ncol=ncol(dem),byrow=T)
t <- raster(t)
projection(t) <- projection(dem)
extent(t) <- extent(dem)
nam <- paste("angle",angle,deflect,"search",max.dist,sep="_")
assign(nam,t)
temp <- get(nam)
writeRaster(temp,nam,format="ascii",overwrite=T)
rm(temp)
gc()
start.ang <- start.ang + 1
}
}
#to execute
out(dem,1,angle.list,3000) #this would calculate the exposure with a
threshold of 1 degree bending (so not much), for the angle list (3 angles),
and search out 3000m
[[alternative HTML version deleted]]
_______________________________________________
R-sig-Geo mailing list
R-sig-Geo@r-project.org
https://stat.ethz.ch/mailman/listinfo/r-sig-geo