我在使用sf制作RMap时遇到了一个问题。我需要使用LAEA投影(CRS 3035),但我的一条水平线是直的,而它应该是弯曲的(中间的那条):
sf
我知道这个问题来自于我在QGIS中创建自定义多边形的方式:我的直线仅由两个点定义,而它应该具有多个节点,例如多边形的左侧:
但我该怎么做呢?我已经找了一个小时的解决方案,但我似乎找不到正确的关键词来实现这一点。有没有一个工具来加密我的行?非常感谢!
oalqel3c1#
您可以使用sf::st_segmentize()来添加点,尽管这可能有点棘手--考虑了坐标系,因此对于沿着纬线的线,纬度值将不会保持不变(检查下面的示例Y是如何变化的)。当分割一个没有CRS的形状时,坐标工作在笛卡尔平面上。不确定是否有更优雅的方法,但首先清除CRS,然后分割,最后重置CRS应该可以让你覆盖。
sf::st_segmentize()
Y
library(sf) #> Linking to GEOS 3.9.3, GDAL 3.5.2, PROJ 8.2.1; sf_use_s2() is TRUE library(ggplot2) # create shape, set CRS sh_wgs84 <- st_bbox(c(xmin = -40, ymin = 40, xmax = 0, ymax = 70), crs = "WGS84") |> st_as_sfc() sh_wgs84 |> st_coordinates() #> X Y L1 L2 #> [1,] -40 40 1 1 #> [2,] 0 40 1 1 #> [3,] 0 70 1 1 #> [4,] -40 70 1 1 #> [5,] -40 40 1 1 # segmentize shape with CRS sh_wgs84_seg <- sh_wgs84 %>% st_segmentize(units::set_units(600, nautical_mile)) sh_wgs84_seg |> st_coordinates() #> X Y L1 L2 #> [1,] -40.000000 40.00000 1 1 #> [2,] -30.134586 41.31607 1 1 #> [3,] -20.000000 41.76330 1 1 #> [4,] -9.865414 41.31607 1 1 #> [5,] 0.000000 40.00000 1 1 #> [6,] 0.000000 47.50000 1 1 #> [7,] 0.000000 55.00000 1 1 #> [8,] 0.000000 62.50000 1 1 #> [9,] 0.000000 70.00000 1 1 #> [10,] -20.000000 71.11828 1 1 #> [11,] -40.000000 70.00000 1 1 #> [12,] -40.000000 62.50000 1 1 #> [13,] -40.000000 55.00000 1 1 #> [14,] -40.000000 47.50000 1 1 #> [15,] -40.000000 40.00000 1 1 # first remove CRS, then segmentize and set CRS sh_seg_wgs84 <- sh_wgs84 %>% st_set_crs(value = NA) %>% st_segmentize(10) |> st_set_crs("WGS84") sh_seg_wgs84 |> st_coordinates() #> X Y L1 L2 #> [1,] -40 40 1 1 #> [2,] -30 40 1 1 #> [3,] -20 40 1 1 #> [4,] -10 40 1 1 #> [5,] 0 40 1 1 #> [6,] 0 50 1 1 #> [7,] 0 60 1 1 #> [8,] 0 70 1 1 #> [9,] -10 70 1 1 #> [10,] -20 70 1 1 #> [11,] -30 70 1 1 #> [12,] -40 70 1 1 #> [13,] -40 60 1 1 #> [14,] -40 50 1 1 #> [15,] -40 40 1 1 # limits for visualization lims <- st_transform(sh_wgs84, 3035) |> st_bbox() World <- rnaturalearth::ne_coastline(returnclass = "sf") p1 <- sh_wgs84_seg |> ggplot() + geom_sf(data = World, linewidth = .2) + geom_sf(fill = "lightblue", alpha = .5) + geom_sf(data = st_cast(sh_wgs84_seg, "POINT")) + coord_sf(crs = 3035, xlim = c(lims$xmin, lims$xmax), ylim = c(lims$ymin, lims$ymax)) + labs(title = "segmentize shape with CRS") + theme_bw() p2 <- sh_seg_wgs84 |> ggplot() + geom_sf(data = World, linewidth = .2) + geom_sf(fill = "gold", alpha = .5) + geom_sf(data = st_cast(sh_seg_wgs84, "POINT")) + coord_sf(crs = 3035, xlim = c(lims$xmin, lims$xmax), ylim = c(lims$ymin, lims$ymax)) + labs(title = "first remove CRS, \nthen segmentize and set CRS") + theme_bw() patchwork::wrap_plots(p1 , p2)
创建于2023年3月3日,使用reprex v2.0.2
1条答案
按热度按时间oalqel3c1#
您可以使用
sf::st_segmentize()
来添加点,尽管这可能有点棘手--考虑了坐标系,因此对于沿着纬线的线,纬度值将不会保持不变(检查下面的示例Y
是如何变化的)。当分割一个没有CRS的形状时,坐标工作在笛卡尔平面上。不确定是否有更优雅的方法,但首先清除CRS,然后分割,最后重置CRS应该可以让你覆盖。
创建于2023年3月3日,使用reprex v2.0.2