Sco*_*ott 5 gradient r raster surface terrain
我想估计未定义表面的梯度(斜率和纵横比)(即函数未知).要测试我的方法,这里是测试数据:
require(raster); require(rasterVis)
set.seed(123)
x <- runif(100, min = 0, max = 1)
y <- runif(100, min = 0, max = 1)
e <- 0.5 * rnorm(100)
test <- expand.grid(sort(x),sort(y))
names(test)<-c('X','Y')
z1 <- (5 * test$X^3 + sin(3*pi*test$Y))
realy <- matrix(z1, 100, 100, byrow = F)
# And a few plots for demonstration #
persp(sort(x), sort(y), realy,
xlab = 'X', ylab = "Y", zlab = 'Z',
main = 'Real function (3d)', theta = 30,
phi = 30, ticktype = "simple", cex=1.4)
contour(sort(x), sort(y), realy,
xlab = 'X', ylab = "Y",
main = 'Real function (contours)', cex=1.4)
Run Code Online (Sandbox Code Playgroud)
我将所有内容转换为栅格并使用绘图rasterVis::vectorplot.一切都很好看.矢量场指示最高变化幅度的方向,阴影类似于我的等高线图...
test.rast <- raster(t(realy), xmn = 0, xmx = 1,
ymn = 0, ymx = 1, crs = CRS("+proj"))
vectorplot(test.rast, par.settings=RdBuTheme, narrow = 100, reverse = T)
Run Code Online (Sandbox Code Playgroud)
但是,我需要一个斜率值矩阵.据我了解vectorplot,它使用raster :: terrain函数:
terr.mast <- list("slope" = matrix(nrow = 100,
ncol = 100,
terrain(test.rast,
opt = "slope",
unit = "degrees",
reverse = TRUE,
neighbors = 8)@data@values,
byrow = T),
"aspect" = matrix(nrow = 100,
ncol = 100,
terrain(test.rast,
opt = "aspect",
unit = "degrees",
reverse = TRUE,
neighbors = 8)@data@values,
byrow = T))
Run Code Online (Sandbox Code Playgroud)
然而,坡度似乎很高......(90度是垂直的,对吗?!)
terr.mast$slope[2:6,2:6]
# [,1] [,2] [,3] [,4] [,5]
#[1,] 87.96546 87.96546 87.96546 87.96550 87.96551
#[2,] 84.68628 84.68628 84.68627 84.68702 84.68709
#[3,] 84.41349 84.41350 84.41349 84.41436 84.41444
#[4,] 84.71757 84.71757 84.71756 84.71830 84.71837
#[5,] 79.48740 79.48741 79.48735 79.49315 79.49367
Run Code Online (Sandbox Code Playgroud)
如果我绘制坡度和坡度,他们似乎不同意矢量图图形.
plot(terrain(test.rast, opt = c("slope", "aspect"), unit = "degrees",
reverse = TRUE, neighbors = 8))
Run Code Online (Sandbox Code Playgroud)
我的想法:
raster::terrain是使用粗纱窗口方法来计算斜率.也许窗户太小了......这可以扩大吗?Osc*_*ñán 11
我RasterLayer使用以下函数构建了一个数据raster:
library(raster)
library(rasterVis)
test.rast <- raster(ncol=100, nrow=100, xmn = 0, xmx = 1, ymn = 0, ymx = 1)
xy <- xyFromCell(test.rast, 1:ncell(test.rast))
test.rast[] <- 5*xy[,1] + sin(3*pi*xy[,2])
Run Code Online (Sandbox Code Playgroud)
让我们用levelplot以下方式显示这个对象:
levelplot(test.rast)
Run Code Online (Sandbox Code Playgroud)

和梯度矢量场vectorplot:
vectorplot(test.rast)
Run Code Online (Sandbox Code Playgroud)

如果您只需要坡度,您可以使用terrain:
slope <- terrain(test.rast, unit='degrees')
levelplot(slope, par.settings=BTCTheme())
Run Code Online (Sandbox Code Playgroud)

但是,如果我理解你,你真的需要渐变,所以你应该计算斜率和方面:
sa <- terrain(test.rast, opt=c('slope', 'aspect'))
Run Code Online (Sandbox Code Playgroud)
为了理解vectorplot绘制箭头的方式,这里我展示了其(修改的)代码的一部分,其中计算了箭头的水平和垂直分量:
dXY <- overlay(sa, fun=function(slope, aspect, ...){
dx <- slope*sin(aspect) ##sin due to the angular definition of aspect
dy <- slope*cos(aspect)
c(dx, dy)
})
Run Code Online (Sandbox Code Playgroud)
由于原件的结构RasterLayer,水平分量几乎是恒定的,所以让我们把注意力放在垂直分量上.下一个代码将向量字段的箭头覆盖在此垂直分量上.
levelplot(dXY, layers=2, par.settings=RdBuTheme()) +
vectorplot(test.rast, region=FALSE)
Run Code Online (Sandbox Code Playgroud)

最后,如果您需要斜率值和方面使用
getValues:
saVals <- getValues(sa)
Run Code Online (Sandbox Code Playgroud)