基于R Grid包的圆周角度绘制方案技术求助
问题解决:用Grid包在圆周边缘正确绘制角度(地理坐标系)
你遇到的核心问题是地理坐标系角度与数学坐标系的转换不匹配,以及箭头绘制的逻辑错误。circular包的geographics模板采用正北为0度、顺时针递增的规则,但默认三角函数是数学坐标系(右为0度、逆时针递增),同时你用viewport旋转的方式绘制箭头也不符合需求。以下是修正方案:
错误点分析
- 角度坐标转换错误:地理坐标系的角度(正北0°,顺时针)不能直接代入数学三角函数计算,需要转换为对应的数学坐标系角度。
- 箭头绘制逻辑错误:通过旋转viewport绘制箭头会导致坐标偏移,应该直接计算箭头端点的笛卡尔坐标。
- 重复pushViewport:代码中多次重复推送同一位置的viewport,造成坐标混乱。
修正后的完整代码
library(grid) # 数据准备 limits <- data.frame(lims = c(57, 75, 42)) angles <- read.table(text =' degree Year 120 2000 30 2001 160 2002 35 2003 150 2004 90 2005 70 2006 20 2007', header = TRUE) # 适配地理坐标系的坐标转换函数 # 地理坐标系:正北为0°,顺时针递增 circ_coords_geo <- function(r, t_deg, h = 0.5, k = 0.5) { t_rad <- t_deg * pi / 180 # 转换为数学坐标系计算:正北对应y轴正方向,顺时针转等价于角度取负 x <- h + r * sin(t_rad) y <- k + r * cos(t_rad) return(c(X = x, Y = y)) } # 绘制圆周点的函数 angles_custom <- function(angles_df, r = 0.5) { lapply(1:nrow(angles_df), function(i) { coord <- circ_coords_geo(r, angles_df$degree[i]) grid.points(x = coord["X"], y = coord["Y"], gp = gpar(pch = 16, col = "black")) }) } # 绘制角度箭头的函数(从中心指向圆周外) limits_custom <- function(limits_df, r_inner = 0.5, r_outer = 0.6) { lapply(1:nrow(limits_df), function(i) { t <- limits_df$lims[i] # 箭头起点(圆周边缘)和终点(圆周外) start <- circ_coords_geo(r_inner, t) end <- circ_coords_geo(r_outer, t) # 绘制线段+箭头 grid.segments(x0 = start["X"], y0 = start["Y"], x1 = end["X"], y1 = end["Y"], gp = gpar(lty = 5, lwd = 2, col = c("red", "red", "blue")[i])) grid.arrows(x0 = start["X"], y0 = start["Y"], x1 = end["X"], y1 = end["Y"], gp = gpar(col = c("red", "red", "blue")[i]), length = unit(0.05, "npc")) }) } # 主绘图逻辑 grid.newpage() # 创建主viewport(避免重复推送) pushViewport(viewport(x = 0.5, y = 0.5, width = 1, height = 1)) # 绘制外圆 grid.circle(x = 0.5, y = 0.5, r = 0.5, gp = gpar(lwd = 3, col = "black")) # 绘制十字参考线 grid.segments(x0 = 0.5, y0 = 0, x1 = 0.5, y1 = 1, gp = gpar(col = "grey")) grid.segments(x0 = 0, y0 = 0.5, x1 = 1, y1 = 0.5, gp = gpar(col = "grey")) # 绘制圆周点和角度箭头 angles_custom(angles) limits_custom(limits) popViewport()
关键修正说明
- 坐标转换适配地理坐标系:将地理角度转换为数学坐标时,使用
sin计算x值、cos计算y值,匹配正北为0°顺时针的规则。 - 直接计算箭头坐标:不再通过旋转viewport,而是直接计算箭头起点(圆周边缘)和终点(圆周外)的坐标,确保箭头指向正确角度。
- 简化viewport层级:只推送一次主viewport,避免坐标混乱。
- 添加箭头样式:用
grid.arrows直接绘制箭头,替代单纯的线段,更符合需求。
内容的提问来源于stack exchange,提问作者Lisa
相关产品推荐
相关产品推荐

