在另一个国家内绘制许多国家

时间:2014-05-21 18:50:12

标签: r map projection area

我想展示巴西亚马逊森林的大小,并在其中绘制不同的国家。就像在这张图片中一样:

enter image description here

为了实现这一点,我加载了一些shapefile并将它们的投影改为一个可以保持区域成比例的投影,如Cylindrical Equal Area:

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)

我得到了这个(没有我后来添加的行):

enter image description here

根据谷歌地球,红线大约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)

here下载shapefile。谢谢大家!

2 个答案:

答案 0 :(得分:2)

首先假设你的国家的边界​​有地理(φ,λ)坐标 - 如果它们是某些制图投影中的(x,y),你必须将它们转换回地理系统。

选择一个顶点,可能是最北端:V(φ0,λ0)并决定它最终落在亚马逊地区的位置:(φ1,λ1)和旋转多少:θ。您将通过几个简单的步骤实现它:

  1. 沿纬度圈滑动形状,使V落在格林威治子午线上 - 你这样做可以从所有经度中减去λ0:
    λ:=λ - λ0

  2. 接下来计算滑动边界的所有顶点的笛卡尔坐标(假设地球表面是球体,而不是椭圆体,更不用说大地水准面,并将地球半径作为长度单位):
    X:=cosλcosφ
    Y:=sinλcosφ
    Z:=sinφ

  3. 将形状滑向南方,使V落在赤道上。这样做可以将(-φ0)角度旋转到XZ平面中的所有顶点:
    X:= X cos(φ0) - Z sin(-φ0)
    Z:= X sin(-φ0)+ Z cos(φ0)

  4. 围绕V顶点旋转边框θ,该顶点目前位于地理坐标(0,0)处的大西洋上 - 这是YZ旋转平面:
    Y:= Y cos(θ) - Z sin(θ)
    Z:= Y sin(θ)+ Z cos(θ)

  5. 现在国界已准备好前往亚马逊森林。首先沿着格林威治子午线向南滑动到所需的纬度(平面XZ旋转φ1 - 注意φ1为负,因为它表示南半球):
    X:= X cos(φ1) - Z sin(φ1)
    Z:= X sin(φ1)+ Z cos(φ1)

  6. 然后将坐标转换为地理系统:
    φ:= asin(Z)
    λ:= asin(Y / cos(φ))

  7. 最后将它们向西滑到南美洲 λ=λ+λ1

  8. 完成。至少我希望如此......;)

  9. 修改

    您也可以在1.之前执行第2步,在第7步之后执行第6步 然后,当然,沿着纬度圈滑动边界不会像λ:=λ+ const那样简单,它必须被计算为XY平面旋转,类似于步骤3到5.这种方式但是,所有转换都将以类似的方式执行,您可以将其描述为矩阵乘法。矩阵乘法是关联的,因此所有系数矩阵都可以提前计算并相乘(按正确的顺序!),然后用单个矩阵乘法转换边界的每个顶点。

    处理完所有国家后,只需将它们全部绘制出来以查看它们是否相交。在这种情况下,调整目标点和θ旋转,直到所有边界都适合亚马逊丛林轮廓而没有碰撞。希望有所帮助。

答案 1 :(得分:1)

我建议尝试使用不同的投影,然后在您生成的地图上绘制天梭的椭圆(下面的前两个链接)。您可以直观地检查地图并选择类似失真的国家/地区。

如果您只想在视觉上进行比较,任何被中断的投影都是最佳的。唯一的问题是存在很多不连续性。每次要创建国家/地区的图像时,都会将投影移动到整个国家/地区(或尽可能多的地方),并且不会出现中断。 只是通过扫描列表,我没有看到任何我认为被打断的内容。如果您不是严格限制这些预测,我推荐Goode的Homolosine,因为它将不连续性放在海洋中。

参考:

该软件(免费)允许您在许多不同的投影上比较(和绘制Tissot的椭圆): http://www.flexprojector.com/