[R-sig-Geo] Speeding raster processing function

Florian Betz FloBetz at web.de
Sat Feb 15 11:10:23 CET 2014


Hi Brian,

maybe you could also have a look at the wind.shelter function in the 
RSAGA package? It gives you an index for the exposure/shelter of a 
surface to the wind and works quite well.
Of course, this does not really solve your code problem, but might be a 
faster alternative...

Regards,

Flo


> 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 at coords[1,1] + distance * cos(angle),0)
>      y <- round(center at 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 at r-project.org
> https://stat.ethz.ch/mailman/listinfo/r-sig-geo



More information about the R-sig-Geo mailing list