如何将Sonar测深数据叠加至OSM湖泊底图并生成等深线?
解决测深数据与OSM底图叠加及生成等深线问题
一、图层合并实现方法
你之前的问题在于将底图和测深点分为两个独立的ggplot对象,只需在同一个ggplot调用中叠加图层即可,同时注意使用coord_sf保证坐标系匹配(OSM数据默认采用WGS84坐标系,即EPSG:4326,与你的CSV经纬度数据一致)。
完整代码如下:
# 加载所需包 library(ggplot2) library(osmdata) library(sf) # 读取测深数据 Sonar_13_07_1 <- read.csv("Sonar_13_07_1.csv") # 定义边界范围 x_coords <- c(-3.109, -3.117) y_coords <- c(39.817, 39.832) # 获取OSM湖泊底图 bounding_box <- matrix(nrow = 2, ncol=2, byrow = T, data = c(x_coords, y_coords), dimnames = list(c("x", "y"), c("min", "max"))) osm_water_sf <- osmdata::opq(bbox = bounding_box) %>% osmdata::add_osm_feature(key = 'natural', value = 'water') %>% osmdata::osmdata_sf() # 叠加底图与测深点 ggplot() + # 绘制OSM湖泊底图 geom_sf(data = osm_water_sf$osm_polygons, color = "blue", fill = "lightblue") + # 绘制测深点,颜色映射水深 geom_point(data = Sonar_13_07_1, aes(x = longitude, y = latitude, colour = waterDepthM), size = 0.5, alpha = 0.7) + # 调小尺寸和透明度避免遮挡 # 设置坐标系与范围 coord_sf(xlim = x_coords, ylim = y_coords, crs = 4326) + # 使用色盲友好的颜色主题 scale_color_viridis_c(option = "plasma", name = "水深(m)") + # 添加标签与主题 labs(x = "经度", y = "纬度", title = "湖泊测深点与OSM底图叠加") + theme_minimal()
二、生成湖泊等深线
基于你的测深数据,可通过两种方式生成等深线:直接使用原始数据绘制,或先插值平滑后绘制。
1. 直接用原始数据绘制等深线
适合数据密度较高的情况(你的3万行数据足够):
ggplot() + geom_sf(data = osm_water_sf$osm_polygons, color = "blue", fill = "lightblue") + # 绘制填充式等深线 geom_contour_filled(data = Sonar_13_07_1, aes(x = longitude, y = latitude, z = waterDepthM), alpha = 0.6) + # 可选:叠加测深点 geom_point(data = Sonar_13_07_1, aes(x = longitude, y = latitude, colour = waterDepthM), size = 0.3, alpha = 0.5) + coord_sf(xlim = x_coords, ylim = y_coords, crs = 4326) + scale_fill_viridis_d(option = "plasma", name = "水深(m)") + scale_color_viridis_c(option = "plasma", name = "水深(m)") + labs(x = "经度", y = "纬度", title = "湖泊等深线与底图叠加") + theme_minimal()
2. 插值平滑后绘制等深线
若原始数据分布不均,可先插值生成栅格数据,得到更平滑的等深线:
# 额外加载插值包 library(interp) library(tidyr) # 对测深数据进行插值 interp_data <- interp(Sonar_13_07_1$longitude, Sonar_13_07_1$latitude, Sonar_13_07_1$waterDepthM, xo = seq(min(x_coords), max(x_coords), length.out = 500), # 经度方向500个点 yo = seq(min(y_coords), max(y_coords), length.out = 500)) # 纬度方向500个点 # 转换为ggplot可用的数据框格式 interp_df <- as.data.frame(interp_data) %>% pivot_longer(cols = -x, names_to = "y", values_to = "waterDepthM") %>% mutate(y = as.numeric(y)) # 绘制平滑等深线 ggplot() + geom_sf(data = osm_water_sf$osm_polygons, color = "blue", fill = "lightblue") + geom_contour_filled(data = interp_df, aes(x = x, y = y, z = waterDepthM), alpha = 0.6) + coord_sf(xlim = x_coords, ylim = y_coords, crs = 4326) + scale_fill_viridis_d(option = "plasma", name = "水深(m)") + labs(x = "经度", y = "纬度", title = "平滑湖泊等深线与底图叠加") + theme_minimal()
内容的提问来源于stack exchange,提问作者Pere Ferriol
相关产品推荐
相关产品推荐

