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

Reply via email to