You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何绘制起止点精确的弯曲箭头?优化R语言自定义函数

优化版弯曲箭头函数实现(支持精确起止点与曲率参数)

直接上可以精准控制起止点的arrow_curved()函数,参数逻辑和基础的arrows()完全对齐,不用再手动调椭圆参数:

arrow_curved <- function(x0, y0, x1, y1, curve = 0.2, length = 0.25, angle = 30, col = par("fg"), lty = par("lty"), lwd = par("lwd")) {
  # 计算起止点中点、距离和垂直方向向量
  mid_x <- (x0 + x1) / 2
  mid_y <- (y0 + y1) / 2
  dx <- x1 - x0
  dy <- y1 - y0
  dist <- sqrt(dx^2 + dy^2)
  
  perp_x <- -dy / dist
  perp_y <- dx / dist
  
  # 基于曲率参数计算椭圆半轴长,确保起止点为椭圆焦点
  a <- (dist + 2 * abs(curve) * dist) / 2
  b <- sqrt(a^2 - (dist/2)^2)
  
  # 根据曲率正负确定椭圆中心偏移方向
  offset_x <- mid_x + curve * perp_x * dist
  offset_y <- mid_y + curve * perp_y * dist
  
  # 计算椭圆旋转角度,匹配箭头方向
  theta <- atan2(dy, dx)
  
  # 生成椭圆上的弧段点集
  t_start <- atan2(y0 - offset_y, x0 - offset_x) - theta
  t_end <- atan2(y1 - offset_y, x1 - offset_x) - theta
  
  # 调整角度范围,确保取到正确的弯曲弧段
  if (curve > 0) {
    if (t_end < t_start) t_end <- t_end + 2*pi
  } else {
    if (t_end > t_start) t_end <- t_end - 2*pi
  }
  
  t_seq <- seq(t_start, t_end, length.out = 100)
  x_curve <- offset_x + a * cos(t_seq) * cos(theta) - b * sin(t_seq) * sin(theta)
  y_curve <- offset_y + a * cos(t_seq) * sin(theta) + b * sin(t_seq) * cos(theta)
  
  # 绘制弯曲箭杆
  lines(x_curve, y_curve, col = col, lty = lty, lwd = lwd)
  
  # 绘制箭头头部,方向匹配曲线切线
  arrow_angle <- theta + ifelse(curve > 0, pi/2, -pi/2)
  x_arrow1 <- x1 + length * cos(arrow_angle + angle * pi/180)
  y_arrow1 <- y1 + length * sin(arrow_angle + angle * pi/180)
  x_arrow2 <- x1 + length * cos(arrow_angle - angle * pi/180)
  y_arrow2 <- y1 + length * sin(arrow_angle - angle * pi/180)
  
  lines(c(x1, x_arrow1), c(y1, y_arrow1), col = col, lty = lty, lwd = lwd)
  lines(c(x1, x_arrow2), c(y1, y_arrow2), col = col, lty = lty, lwd = lwd)
}

参数说明

  • x0, y0/x1, y1: 箭头的起点/终点坐标,和arrows()完全一致
  • curve: 曲率控制,正数向右弯,负数向左弯,绝对值越大弯度越夸张(推荐范围-0.5~0.5)
  • length/angle: 箭头头部的长度和张开角度,和arrows()参数逻辑相同
  • col/lty/lwd: 箭杆和箭头的颜色、线型、线宽,兼容基础绘图参数

用法示例

# 绘制不同方向、曲率的弯曲箭头
plot(0, 0, xlim = c(-2, 2), ylim = c(-2, 2), type = "n", main = "弯曲箭头演示")
arrow_curved(-1, -1, 1, 1, curve = 0.3, col = "red")
arrow_curved(-1, 1, 1, -1, curve = -0.3, col = "blue")
arrow_curved(0, -1.5, 0, 1.5, curve = 0.2, col = "green")
arrow_curved(-1.5, 0, 1.5, 0, curve = -0.2, col = "purple")

# 叠加直线箭头做对比
arrows(-1, -1, 1, 1, col = "gray", lty = 2)

这个函数的核心是把起止点作为椭圆的两个焦点,通过curve参数动态调整椭圆形状,确保曲线严格经过指定的起点和终点,不会出现之前的近似偏移问题,用起来和arrows()一样顺手。

内容的提问来源于stack exchange,提问作者jay.sf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:00:58