如何在geom_sf与ggplot2绘制的地图上为边界两点间线段着色
土耳其西部边界指定线段着色解决方案
核心思路
先提取目标边界(国界或省界),定位边界上的两个目标点,截取两点间的线段后单独着色,避开复杂的st_intersect直接处理边界线的坐标序列。
步骤1:准备数据与环境
加载所需包,获取土耳其省份和国家级边界数据:
library(sf) library(rnaturalearth) library(rnaturalearthdata) library(ggplot2) library(dplyr) # 加载土耳其省份数据 turkey_provinces <- ne_states(country = "turkey", returnclass = "sf") # 获取土耳其国家级边界并转为线串格式 turkey_boundary <- ne_countries(country = "turkey", returnclass = "sf") %>% st_cast("LINESTRING")
步骤2:确定西部边界的目标点
你可以手动指定经纬度(比如西部沿海的两个点),或者从边界采样点中选择:
# 示例:手动指定西部边界的两个点(经纬度) point1 <- st_point(c(26.2, 38.8)) %>% st_sfc(crs = st_crs(turkey_boundary)) point2 <- st_point(c(28.3, 40.6)) %>% st_sfc(crs = st_crs(turkey_boundary))
步骤3:截取两点间的边界线段
通过细分边界点、匹配最近点,提取目标线段:
# 细分边界线生成采样点,提升定位精度 boundary_sample <- st_line_sample(turkey_boundary, n = 1000) %>% st_cast("POINT") %>% st_sf() # 找到目标点在边界上的最近匹配点 nearest_p1 <- boundary_sample[st_nearest_feature(point1, boundary_sample), ] nearest_p2 <- boundary_sample[st_nearest_feature(point2, boundary_sample), ] # 获取边界线的坐标序列,定位两个最近点的索引 boundary_coords <- st_coordinates(turkey_boundary)[, 1:2] idx_p1 <- which.min(sqrt((boundary_coords[,1] - st_coordinates(nearest_p1)[1])^2 + (boundary_coords[,2] - st_coordinates(nearest_p1)[2])^2)) idx_p2 <- which.min(sqrt((boundary_coords[,1] - st_coordinates(nearest_p2)[1])^2 + (boundary_coords[,2] - st_coordinates(nearest_p2)[2])^2)) # 修正索引顺序,确保从左到右/从南到北截取 start_idx <- min(idx_p1, idx_p2) end_idx <- max(idx_p1, idx_p2) # 生成目标线段的sf对象 target_segment <- st_linestring(boundary_coords[start_idx:end_idx, ]) %>% st_sfc(crs = st_crs(turkey_boundary)) %>% st_sf()
步骤4:绘制带着色线段的地图
叠加底图、完整边界和目标线段,设置不同颜色区分:
ggplot() + # 省份底图 geom_sf(data = turkey_provinces, fill = "#f0f0f0", color = "white", linewidth = 0.2) + # 完整边界(灰色打底) geom_sf(data = turkey_boundary, color = "gray60", linewidth = 0.5) + # 目标线段(红色高亮) geom_sf(data = target_segment, color = "#e74c3c", linewidth = 1.2) + ggthemes::theme_map()
适配省界的调整
如果要着色的是西部省份之间的内部边界,只需把turkey_boundary替换为西部省份的边界数据:
# 提取伊兹密尔、马尼萨等西部省份的边界 west_provinces <- turkey_provinces %>% filter(name %in% c("Izmir", "Manisa", "Aydin")) %>% st_union() %>% st_cast("LINESTRING") %>% st_sf()
之后重复步骤2-4即可处理省界线段。
内容的提问来源于stack exchange,提问作者mzkrc
相关产品推荐
相关产品推荐

