如何用ggplot2+sf可视化OpenTracks的KML驾驶轨迹并计算总里程?
解决OpenTracks KML轨迹可视化与里程计算问题
一、正确解析KML到合法sf对象
你用xml2手动解析时大概率没把坐标整理成sf要求的结构,尤其是KML的坐标格式是经度在前、纬度在后,搞反或格式错误直接导致后续报错。以下是标准解析流程:
library(xml2) library(sf) # 读取KML文件 kml <- read_xml("your_business_track.kml") # 移除KML命名空间(避免节点查找失败) kml <- xml_ns_strip(kml) # 提取轨迹坐标文本 coords_text <- xml_text(xml_find_first(kml, ".//coordinates"), trim = TRUE) # 拆分每个坐标点(按空格分隔) coords_list <- strsplit(coords_text, "\\s+")[[1]] # 拆分每个点的经纬度(丢弃KML自带的海拔值) coords_matrix <- do.call(rbind, strsplit(coords_list, ","))[, 1:2] %>% as.numeric() # 转成sf LINESTRING对象(设置WGS84坐标系,对应GPS数据) track_sf <- st_sfc(st_linestring(coords_matrix), crs = 4326) %>% st_sf(geometry = ., track_id = 1)
二、修复geom_sf报错(条件长度大于1)
这个报错90%是因为sf对象不合法,先做有效性检查:
# 查看sf对象结构,确保geometry列是单一类型(LINESTRING) str(track_sf) # 验证几何有效性,无效则修复 if (!all(st_is_valid(track_sf))) { track_sf <- st_make_valid(track_sf) }
然后用标准代码绘图,注意关闭继承美学映射避免冲突:
library(ggplot2) ggplot() + geom_sf(data = track_sf, color = "#e74c3c", linewidth = 1.2, inherit.aes = FALSE) + theme_minimal() + labs(title = "商务驾驶轨迹")
如果需要叠加底图,用基础maps包即可:
library(maps) # 加载对应区域的底图数据(以美国为例) region_map <- map_data("state") ggplot() + geom_polygon(data = region_map, aes(x = long, y = lat, group = group), fill = "#f0f0f0", color = "#ffffff") + geom_sf(data = track_sf, color = "#c0392b", linewidth = 1.2, inherit.aes = FALSE) + coord_sf(crs = 4326) + theme_minimal()
三、计算插值轨迹总里程(英里)
直接用sf的长度计算函数,转换单位即可:
# 计算轨迹长度(默认单位为米) track_length_m <- st_length(track_sf) # 转换为英里(1英里=1609.34米) track_length_mi <- as.numeric(track_length_m) / 1609.34 # 输出结果 cat("商务驾驶总里程:", round(track_length_mi, 2), "英里\n")
如果轨迹点太稀疏需要插值加密:
# 按0.1%间隔插值加密轨迹点 interpolated_points <- st_line_interpolate_points(track_sf$geometry[[1]], seq(0, 1, by = 0.001)) # 转成LINESTRING对象 interpolated_line <- st_cast(st_sfc(interpolated_points), "LINESTRING") # 计算插值后的里程 interpolated_mi <- as.numeric(st_length(interpolated_line)) / 1609.34
内容的提问来源于stack exchange,提问作者GNUser
相关产品推荐
相关产品推荐

