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

点与两条指定圆弧的最短距离计算方法技术问询

计算点到两条扫出圆弧的最短距离

我来一步步拆解这个问题,帮你搞定任意点到这两条圆弧的最短距离计算——核心思路是先算出点到每条圆弧的距离,再取两者里更小的那个。

首先得明确两条目标圆弧的定义:它们都是以点$c$为旋转中心,分别以$r-R$和$r+R$为半径,从原点指向中心的方向开始,绕$c$扫过$\theta$角形成的一段弧(简单说就是从“中心到原点”的反向延长线与对应半径圆的交点出发,转$\theta$角的一段弧)。

第一步:先搞定点到单段圆弧的最短距离

对于任意一段圆弧,点到它的最短距离分三种情况,我们一个个说:

1. 先确定圆弧的关键参数

首先得算出圆弧的起始点$S$、终止点$E$,以及它覆盖的角度范围:

  • 起始点$S$:把“中心$c$到原点$O$”的向量反向,缩放到圆弧半径的长度,得到的点就是$S$。公式是:
    $\overrightarrow{cO} = O - c = (-c_x, -c_y)$,单位化后乘以圆弧半径$R_{arc}$(这里$R_{arc}$分别取$r-R$和$r+R$),再加上中心$c$的坐标,就是$S$的坐标。
  • 终止点$E$:把$S$绕$c$旋转$\theta$角得到的点,旋转公式用标准的二维旋转公式就行:
    $E_x = c_x + (S_x - c_x)\cos\theta - (S_y - c_y)\sin\theta$
    $E_y = c_y + (S_x - c_x)\sin\theta + (S_y - c_y)\cos\theta$
  • 角度范围:以$c$为极点,起始角度$\alpha_0 = \text{atan2}(S_y - c_y, S_x - c_x)$,终止角度$\alpha_1 = \alpha_0 + \theta$。注意要把角度统一到$[0, 2\pi]$区间,处理跨0度的情况(比如从350度转到10度的圆弧)。

2. 判断点相对于圆弧的位置,计算距离

接下来看点$P$相对于中心$c$的角度$\alpha_p = \text{atan2}(P_y - c_y, P_x - c_x)$,然后分三种情况:

  • 情况1:点$P$的角度在圆弧的角度范围内
    这时候点到圆弧的最短距离就是点到圆弧所在圆的距离,也就是$|d - R_{arc}|$,其中$d$是$P$到$c$的直线距离($\sqrt{(P_x - c_x)^2 + (P_y - c_y)^2}$)。
  • 情况2:点$P$的角度在圆弧起始角的外侧
    这时候点到圆弧的最短距离就是$P$到圆弧起始点$S$的直线距离。
  • 情况3:点$P$的角度在圆弧终止角的外侧
    这时候最短距离就是$P$到圆弧终止点$E$的直线距离。

第二步:计算两条圆弧的距离,取最小值

分别算出点$P$到半径为$r-R$的圆弧距离$d_1$,以及到半径为$r+R$的圆弧距离$d_2$,最终返回$\min(d_1, d_2)$就完事了。

给你个伪代码参考

import math

def point_to_single_arc(P, center, arc_radius, sweep_angle):
    px, py = P
    cx, cy = center
    
    # 计算起始点S
    vec_center_to_origin = (-cx, -cy)
    len_vec = math.hypot(*vec_center_to_origin)
    if len_vec < 1e-9:
        # 特殊情况:中心在原点,圆弧从(arc_radius, 0)开始扫
        start_x, start_y = arc_radius, 0
    else:
        unit_vec = (vec_center_to_origin[0]/len_vec, vec_center_to_origin[1]/len_vec)
        start_x = cx + unit_vec[0] * arc_radius
        start_y = cy + unit_vec[1] * arc_radius
    
    # 计算终止点E
    dx = start_x - cx
    dy = start_y - cy
    end_x = cx + dx * math.cos(sweep_angle) - dy * math.sin(sweep_angle)
    end_y = cy + dx * math.sin(sweep_angle) + dy * math.cos(sweep_angle)
    
    # 处理角度范围(统一到[0, 2π])
    start_angle = math.atan2(start_y - cy, start_x - cx) % (2 * math.pi)
    end_angle = (start_angle + sweep_angle) % (2 * math.pi)
    point_angle = math.atan2(py - cy, px - cx) % (2 * math.pi)
    
    # 判断点是否在圆弧角度范围内
    in_arc_range = False
    if start_angle <= end_angle:
        in_arc_range = start_angle <= point_angle <= end_angle
    else:
        # 跨0度的圆弧,比如从350度到10度
        in_arc_range = point_angle >= start_angle or point_angle <= end_angle
    
    if in_arc_range:
        # 点在圆弧角度范围内,取到圆的距离
        dist_to_center = math.hypot(px - cx, py - cy)
        return abs(dist_to_center - arc_radius)
    else:
        # 计算到两个端点的距离,取更近的那个
        dist_to_start = math.hypot(px - start_x, py - start_y)
        dist_to_end = math.hypot(px - end_x, py - end_y)
        return min(dist_to_start, dist_to_end)

def get_min_arc_distance(P, c, theta, r, R):
    dist_inner = point_to_single_arc(P, c, r - R, theta)
    dist_outer = point_to_single_arc(P, c, r + R, theta)
    return min(dist_inner, dist_outer)

几个要注意的细节

  • 单位问题:代码里用的是弧度,如果你的$\theta$是角度值,记得先转成弧度($\theta_{rad} = \theta_{deg} \times \pi / 180$)。
  • 精度处理:浮点数计算时要加小阈值判断(比如$len_vec < 1e-9$),避免除以0的错误。
  • 中心在原点的特殊情况:这时候圆弧的起始点可以直接设为$(arc_radius, 0)$,如果你的需求里起始方向不是x轴,得根据实际情况调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:47:15