我想展示巴西亚马逊森林的大小,并在其中绘制不同的国家。就像在这张图片中一样:
为了实现这一点,我加载了一些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)
我得到了这个(没有我后来添加的行):
根据谷歌地球,红线大约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。谢谢大家!
答案 0 :(得分:2)
首先假设你的国家的边界有地理(φ,λ)坐标 - 如果它们是某些制图投影中的(x,y),你必须将它们转换回地理系统。
选择一个顶点,可能是最北端:V(φ0,λ0)并决定它最终落在亚马逊地区的位置:(φ1,λ1)和旋转多少:θ。您将通过几个简单的步骤实现它:
沿纬度圈滑动形状,使V落在格林威治子午线上 - 你这样做可以从所有经度中减去λ0:
λ:=λ - λ0
接下来计算滑动边界的所有顶点的笛卡尔坐标(假设地球表面是球体,而不是椭圆体,更不用说大地水准面,并将地球半径作为长度单位):
X:=cosλcosφ
Y:=sinλcosφ
Z:=sinφ
将形状滑向南方,使V落在赤道上。这样做可以将(-φ0)角度旋转到XZ平面中的所有顶点:
X:= X cos(φ0) - Z sin(-φ0)
Z:= X sin(-φ0)+ Z cos(φ0)
围绕V顶点旋转边框θ,该顶点目前位于地理坐标(0,0)处的大西洋上 - 这是YZ旋转平面:
Y:= Y cos(θ) - Z sin(θ)
Z:= Y sin(θ)+ Z cos(θ)
现在国界已准备好前往亚马逊森林。首先沿着格林威治子午线向南滑动到所需的纬度(平面XZ旋转φ1 - 注意φ1为负,因为它表示南半球):
X:= X cos(φ1) - Z sin(φ1)
Z:= X sin(φ1)+ Z cos(φ1)
然后将坐标转换为地理系统:
φ:= asin(Z)
λ:= asin(Y / cos(φ))
最后将它们向西滑到南美洲 λ=λ+λ1
完成。至少我希望如此......;)
修改强>
您也可以在1.之前执行第2步,在第7步之后执行第6步 然后,当然,沿着纬度圈滑动边界不会像λ:=λ+ const那样简单,它必须被计算为XY平面旋转,类似于步骤3到5.这种方式但是,所有转换都将以类似的方式执行,您可以将其描述为矩阵乘法。矩阵乘法是关联的,因此所有系数矩阵都可以提前计算并相乘(按正确的顺序!),然后用单个矩阵乘法转换边界的每个顶点。
处理完所有国家后,只需将它们全部绘制出来以查看它们是否相交。在这种情况下,调整目标点和θ旋转,直到所有边界都适合亚马逊丛林轮廓而没有碰撞。希望有所帮助。
答案 1 :(得分:1)
我建议尝试使用不同的投影,然后在您生成的地图上绘制天梭的椭圆(下面的前两个链接)。您可以直观地检查地图并选择类似失真的国家/地区。
如果您只想在视觉上进行比较,任何被中断的投影都是最佳的。唯一的问题是存在很多不连续性。每次要创建国家/地区的图像时,都会将投影移动到整个国家/地区(或尽可能多的地方),并且不会出现中断。 只是通过扫描列表,我没有看到任何我认为被打断的内容。如果您不是严格限制这些预测,我推荐Goode的Homolosine,因为它将不连续性放在海洋中。
参考:
该软件(免费)允许您在许多不同的投影上比较(和绘制Tissot的椭圆): http://www.flexprojector.com/