【发布时间】:2014-07-10 14:02:56
【问题描述】:
我想展示巴西亚马逊森林有多大,在其中绘制不同的国家。就像这张图片:
为了实现这一点,我加载了一些 shapefile 并将它们的投影更改为保持区域成比例的投影,例如圆柱等面积:
library(rgdal)
countries <- readOGR("shp","TM_WORLD_BORDERS-0.3")
countries <- spTransform(countries,CRS("+proj=cea"))
amzLegal <- readOGR("shp","amazlegal")
amzLegal@proj4string <- CRS("+proj=longlat")
amzLegal <- spTransform(amzLegal,CRS("+proj=cea"))
plot(amzLegal)
FR <- countries[which(countries$NAME == "France"),]
for (i in 1:length(FR@polygons[[1]]@Polygons)) {
FR@polygons[[1]]@Polygons[[i]]@coords[,1] = FR@polygons[[1]]@Polygons[[i]]@coords[,1]-7180000
FR@polygons[[1]]@Polygons[[i]]@coords[,2] = FR@polygons[[1]]@Polygons[[i]]@coords[,2]-4930000
}
plot(FR,col="blue",add=T)
我得到了这个(不包括我稍后添加的行):
根据 Google 地球,红线约为 950 公里(在法国),与黑线(在巴西)的长度相同。因此,圆柱等面积当然不是合适的投影,因为它扩大了经度并缩小了纬度。那我应该使用什么投影呢?一个保持形状和大小的?我也尝试过 Lambert Azimuthal Equal Area,但也没有用。我喜欢 Goode 的 Homolosine,但它并不是真正的单一投影,而是不同技术的混合。以下是可能的预测列表:http://www.remotesensing.org/geotiff/proj_list/
编辑:在@CiaPan 回答之后,我来到了这个函数:
translate <- function(obj,x,y,ang=0,adiciona=T) {
maxLat <- -90
for (i in 1:length(obj@polygons[[1]]@Polygons)) {
for (j in 1:nrow(obj@polygons[[1]]@Polygons[[i]]@coords)) {
lat <- obj@polygons[[1]]@Polygons[[i]]@coords[j,2]
if (lat > maxLat) {
maxLat <- lat
maxLon <- obj@polygons[[1]]@Polygons[[i]]@coords[j,1]
}
}
}
lon0 <- maxLon*pi/180
lat0 <- maxLat*pi/180
y <- y*pi/180 # degrees to radians
ang <- ang*pi/180
x1 = 180
x2 = -180
y1 = 90
y2 = -90
for (i in 1:length(obj@polygons[[1]]@Polygons)) {
for (j in 1:nrow(obj@polygons[[1]]@Polygons[[i]]@coords)) {
lon <- obj@polygons[[1]]@Polygons[[i]]@coords[j,1]*pi/180 - lon0 #1 V to Greenwich
lat <- obj@polygons[[1]]@Polygons[[i]]@coords[j,2]*pi/180
X <- cos(lon)*cos(lat) #2 Cartesian coords
Y <- sin(lon)*cos(lat)
Z <- sin(lat)
X0 <- X
X <- X0*cos(lat0) - Z*sin(-lat0) #3 V to Equator
Z <- X0*sin(-lat0) + Z*cos(lat0)
Y0 <- Y
Y <- Y0*cos(ang) - Z*sin(ang) #4 rotate by ang
Z <- Y0*sin(ang) + Z*cos(ang)
X0 <- X
X <- X0*cos(y) - Z*sin(y) #5 V to y
Z <- X0*sin(y) + Z*cos(y)
lat <- asin(Z) #6
lon <- asin(Y/cos(lat))*180/pi + x
lat <- lat*180/pi
if (lon < x1) { x1 <- lon } #bbox
if (lon > x2) { x2 <- lon }
if (lat < y1) { y1 <- lat }
if (lat > y2) { y2 <- lat }
obj@polygons[[1]]@Polygons[[i]]@coords[j,1] <- lon
obj@polygons[[1]]@Polygons[[i]]@coords[j,2] <- lat
}
}
obj@bbox[1,1] <- x1
obj@bbox[1,2] <- x2
obj@bbox[2,1] <- y1
obj@bbox[2,2] <- y2
plot(obj,col="red",border="black",add=adiciona)
}
其中 obj 是一个 spatialPolygons 对象,x 和 y 是目标的 long 和 lat。该函数翻译并绘制对象。用法可以是:
library(rgdal)
par(mar=c(0,0,0,0))
countries <- readOGR("shp","TM_WORLD_BORDERS-0.3",encoding="UTF-8")
plot(countries,col=rgb(1,0.8,0.4))
translate(countries[which(countries$NAME == "France"),],-60,0,0,T)
shapefile 是从here 下载的。谢谢大家!
【问题讨论】:
-
IMVHO 最好将地理轮廓滑过球体(可能进行一些旋转)以适应亚马逊边界,然后使用任何选择的方法将它们全部投影到平面中。
-
你的意思是做这一步 (FR@polygons[[1]]@Polygons[[i]]@coords[,1] = FR@polygons[[1]]@Polygons[[i] ]@coords[,1]-7180000) 为整个欧洲大陆,然后才投射它们?如果这就是你的建议,那就不行了,因为高纬度的 1 度大于靠近赤道线的 1 度。
-
不管怎样,让我吃惊的是,在上面的第一张地图中,法国是多么的小!这是一个不同的预测,还是只是一个错误?
-
我说的是“在 sphere 上滑动”而不是 plane,这意味着将 3D 旋转应用于描述国家/地区在 3D 空间中的顶点的 3D 向量,其中存在地球球体。向平面或地理坐标添加常数是无稽之谈,如果添加纬度,您可能会越过地球极点!
-
好吧,我不知道该怎么做。你能推荐任何教程吗?谢谢!
标签: r map projection area