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

ggforce geom_arc使用问题:如何计算atan2并将圆弧绘制在指定侧

解决方案

核心原理:ggforce::geom_arc默认沿逆时针方向从start角度绘制到end角度,只要保证end与start的逆时针差值等于你计算出的带符号最小夹角arc_deg(弧度制),就能自动落在夹角更小的一侧,不需要复杂的多场景判断。

具体修改逻辑

  • 你已经计算出了带符号的最小夹角arc_deg,如果该值为负,说明逆时针从arcAB到arcBC的实际跨度超过180°,只需要给arcBC加2*pi就能得到正确的逆时针小夹角终点
  • 原有角度标注的坐标计算为A、C中点,可能落到夹角外侧,建议改为基于圆弧中点角度计算标注位置,和圆弧方向匹配

完整可运行代码

# 加载依赖包
library(tidyverse)
library(ggforce)

tmp <- tibble(xA = c(11, 14, 11, 14), yA = c(8, 8, 7, 7),
              xB = c(10, 15, 10, 15), yB = c(10, 10, 5, 5),
              xC = c(8, 17, 8, 17), yC = c(11, 11, 4, 4))

tmp <- tmp %>%
  # 计算AB、BC距离
  mutate(dAB = sqrt((xA - xB)^2 + (yA - yB)^2),
         dBC = sqrt((xB - xC)^2 + (yB - yC)^2)) %>%
  # 计算AB、BC相对于B点的弧度
  mutate(arcAB = atan2(yA - yB, xA - xB),
         arcBC = atan2(yC - yB, xC - xB)) %>%
  # 计算带符号的最小角度(角度制)
  mutate(arc_deg = round((arcBC * (180 / pi)) - (arcAB *  (180 / pi)), 1)) %>%
  mutate(arc_deg = case_when(
    arc_deg >  180 ~ arc_deg - 360,
    arc_deg < -180 ~ arc_deg + 360,
    TRUE           ~ arc_deg)) %>%
  # 调整geom_arc的终点角度,保证逆时针跨度为最小夹角
  mutate(arc_end = ifelse(arc_deg < 0, arcBC + 2*pi, arcBC)) %>%
  # 计算圆弧中点角度,用于标注位置
  mutate(mid_angle = arcAB + arc_deg*pi/180/2) %>%
  # 计算标注位置:在B点到圆弧中点的连线上,距离B点1.2倍dAB的位置(可按需调整系数)
  mutate(label_x = xB + dAB * 1.2 * cos(mid_angle),
         label_y = yB + dAB * 1.2 * sin(mid_angle))

# 绘图
ggplot(tmp) + 
  geom_segment(aes(x = xB, xend = xA, y = yB, yend = yA), size = 1, col = "blue") +
  geom_segment(aes(x = xB, xend = xC, y = yB, yend = yC), size = 1, col = "green") +
  geom_text(aes(x = xB + 0.2, y = yB), label = "B") +
  geom_text(aes(x = xA + 0.2, y = yA), label = "A") +
  geom_text(aes(x = xC - 0.2, y = yC), label = "C") +
  # 用调整后的arc_end作为终点
  geom_arc(aes(x0 = xB, y0 = yB, r = dAB, start = arcAB, end = arc_end)) +
  # 用修正后的位置标注角度
  geom_text(aes(x = label_x, y = label_y, label = paste0(arc_deg, "°"))) +
  coord_fixed() + 
  theme_bw()

扩展说明

如果需要强制顺时针绘制圆弧,只需要调整逻辑:判断如果arc_deg为正,给arcAB加2*pi,交换start和end即可,不需要额外处理其他场景。

内容的提问来源于stack exchange,提问作者Rumpl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:24:04