如何在 R 中旋转地图
How rotate map in R
我只想旋转地图,或改变方向,例如 45 度,而不是其他元素。有可能吗?
例如:
- 不旋转图像
- 旋转图像
我没有旋转的初始代码:
library("maps")
library("mapproj")
library("mapdata")
xlon = seq(-1, 7, 0.01)
xlat = seq(34, 42, 0.01)
map(database = "worldHires",
xlim = c(min(xlon), max(xlon)), ylim = c(min(xlat),max(xlat)),
mar = c(0, 0, 0, 0))
text(2, 37, labels = "point1", pos = 4)
points(2, 37)
通常当您调用 maps::map()
时,它会在函数调用期间自动绘制地图,但您可以传递 plot=F
来防止这种情况发生。同时,您可以将调用中的 return 值存储在一个变量中,该变量将包含所请求地图等高线的 x 和 y 坐标。然后,您可以使用一些三角函数围绕中心点旋转所有 x 和 y 坐标,最后使用基本 R 绘图函数手动绘制旋转点。
library('maps');
library('mapproj');
library('mapdata');
xlon = seq(-1,7,0.01);
xlat = seq(34,42,0.01);
md <- map('worldHires',xlim=range(xlon),ylim=range(xlat),mar=c(0,0,0,0),plot=F);
md2 <- md;
rot <- -30*pi/180;
about <- c(2,37);
newangles <- atan2(md$y-about[2],md$x-about[1])+rot;
mags <- sqrt((md$x-about[1])^2+(md$y-about[2])^2);
md2$x <- about[1]+cos(newangles)*mags;
md2$y <- about[2]+sin(newangles)*mags;
par(mar=c(0,0,0,0)); plot(md2,type='l',xlim=range(xlon),ylim=range(xlat),axes=F,ann=F);
text(about[1],about[2],labels='point1',pos=4);
points(about[1],about[2]);
如果您没有与 R 紧密集成,您可以通过 emptymap.js here is the article 解释用法来探索地图旋转。
免责声明:我是该模块的开发者。
现在是 2021 年了,使用现代 sf
R 包要容易得多。有了这个,您可以在绘图之前旋转底层的多边形以获得所需的效果。这也通过 rnaturalearth
包使用来自 Natural Earth 的国家多边形数据。
library(sf)
library(rnaturalearth)
library(ggplot2)
# Rotate an sf geom around a center point. If no center is
# specified then it rotates around the center of the geom.
# This is technically an affine transformation: https://r-spatial.github.io/sf/articles/sf3.html#affine-transformations-1
st_ellide_rotate = function(x, degrees, center_coords=NULL){
if(degrees < -360 | degrees > 360) stop('Degrees must be in the range -360 to 360')
x = sf::st_combine(x)
if(is.null(center_coords)){
center_coords = sf::st_centroid(x)
}
radians = degrees * pi/180
transform_matrix = matrix(c(cos(radians), sin(radians), -sin(radians), cos(radians)), 2, 2)
return((x-center_coords) * transform_matrix + center_coords)
}
countries = rnaturalearth::ne_countries(scale = 10,returnclass = 'sf')
saved_crs = st_crs(countries)
points = st_sf(name=c('point1'), geometry = st_sfc(st_point(c(2,37)), crs = saved_crs))
countries_rotated = countries %>%
st_ellide_rotate(-20, center_coords = c(2,37))
# applying an affine transformation nulls the CRS for some reason, so reset it here
st_crs(countries_rotated) <- saved_crs
ggplot() +
geom_sf(data=countries_rotated) +
geom_sf(data=points, size=1) +
geom_sf_label(data=points, aes(label=name), nudge_x=1) +
coord_sf(xlim = c(-1,7), ylim=c(34,42)) +
labs(subtitle = 'rotated 20 deg')
ggplot() +
geom_sf(data=countries) +
geom_sf(data=points, size=1) +
geom_sf_label(data=points, aes(label=name), nudge_x = 1) +
coord_sf(xlim = c(-1,7), ylim=c(34,42)) +
labs(subtitle = 'original')
我只想旋转地图,或改变方向,例如 45 度,而不是其他元素。有可能吗? 例如:
- 不旋转图像
- 旋转图像
我没有旋转的初始代码:
library("maps")
library("mapproj")
library("mapdata")
xlon = seq(-1, 7, 0.01)
xlat = seq(34, 42, 0.01)
map(database = "worldHires",
xlim = c(min(xlon), max(xlon)), ylim = c(min(xlat),max(xlat)),
mar = c(0, 0, 0, 0))
text(2, 37, labels = "point1", pos = 4)
points(2, 37)
通常当您调用 maps::map()
时,它会在函数调用期间自动绘制地图,但您可以传递 plot=F
来防止这种情况发生。同时,您可以将调用中的 return 值存储在一个变量中,该变量将包含所请求地图等高线的 x 和 y 坐标。然后,您可以使用一些三角函数围绕中心点旋转所有 x 和 y 坐标,最后使用基本 R 绘图函数手动绘制旋转点。
library('maps');
library('mapproj');
library('mapdata');
xlon = seq(-1,7,0.01);
xlat = seq(34,42,0.01);
md <- map('worldHires',xlim=range(xlon),ylim=range(xlat),mar=c(0,0,0,0),plot=F);
md2 <- md;
rot <- -30*pi/180;
about <- c(2,37);
newangles <- atan2(md$y-about[2],md$x-about[1])+rot;
mags <- sqrt((md$x-about[1])^2+(md$y-about[2])^2);
md2$x <- about[1]+cos(newangles)*mags;
md2$y <- about[2]+sin(newangles)*mags;
par(mar=c(0,0,0,0)); plot(md2,type='l',xlim=range(xlon),ylim=range(xlat),axes=F,ann=F);
text(about[1],about[2],labels='point1',pos=4);
points(about[1],about[2]);
如果您没有与 R 紧密集成,您可以通过 emptymap.js here is the article 解释用法来探索地图旋转。
免责声明:我是该模块的开发者。
现在是 2021 年了,使用现代 sf
R 包要容易得多。有了这个,您可以在绘图之前旋转底层的多边形以获得所需的效果。这也通过 rnaturalearth
包使用来自 Natural Earth 的国家多边形数据。
library(sf)
library(rnaturalearth)
library(ggplot2)
# Rotate an sf geom around a center point. If no center is
# specified then it rotates around the center of the geom.
# This is technically an affine transformation: https://r-spatial.github.io/sf/articles/sf3.html#affine-transformations-1
st_ellide_rotate = function(x, degrees, center_coords=NULL){
if(degrees < -360 | degrees > 360) stop('Degrees must be in the range -360 to 360')
x = sf::st_combine(x)
if(is.null(center_coords)){
center_coords = sf::st_centroid(x)
}
radians = degrees * pi/180
transform_matrix = matrix(c(cos(radians), sin(radians), -sin(radians), cos(radians)), 2, 2)
return((x-center_coords) * transform_matrix + center_coords)
}
countries = rnaturalearth::ne_countries(scale = 10,returnclass = 'sf')
saved_crs = st_crs(countries)
points = st_sf(name=c('point1'), geometry = st_sfc(st_point(c(2,37)), crs = saved_crs))
countries_rotated = countries %>%
st_ellide_rotate(-20, center_coords = c(2,37))
# applying an affine transformation nulls the CRS for some reason, so reset it here
st_crs(countries_rotated) <- saved_crs
ggplot() +
geom_sf(data=countries_rotated) +
geom_sf(data=points, size=1) +
geom_sf_label(data=points, aes(label=name), nudge_x=1) +
coord_sf(xlim = c(-1,7), ylim=c(34,42)) +
labs(subtitle = 'rotated 20 deg')
ggplot() +
geom_sf(data=countries) +
geom_sf(data=points, size=1) +
geom_sf_label(data=points, aes(label=name), nudge_x = 1) +
coord_sf(xlim = c(-1,7), ylim=c(34,42)) +
labs(subtitle = 'original')