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

如何将物体移动限制在两个重叠半径的交集区域内?

两圆交集区域的幅值钳制方案

针对你提出的「将物体移动范围钳制在两个仅单点重叠(相切)的圆的交集内」的需求,以下是具体的数学推导和实现方法:

基础定义

先明确两个圆的参数:

  • 圆1:圆心 ( \mathbf{C_1} = (x_1, y_1) ),半径 ( r_1 )
  • 圆2:圆心 ( \mathbf{C_2} = (x_2, y_2) ),半径 ( r_2 )

两圆仅单点重叠(相切),分为两种情况:

  1. 外切:圆心距 ( d = |\mathbf{C_1} - \mathbf{C_2}| = r_1 + r_2 ),交集为单个切点
  2. 内切:圆心距 ( d = |r_1 - r_2| ),交集为整个较小的圆

核心逻辑

要让物体位置 ( \mathbf{P} = (x, y) ) 落在两圆交集内,必须同时满足:

  • 到 ( \mathbf{C_1} ) 的距离 ≤ ( r_1 )
  • 到 ( \mathbf{C_2} ) 的距离 ≤ ( r_2 )

若位置超出交集,需将其拉回至交集的边界或内部。


分步实现(2D场景)

1. 检查当前位置合法性

计算物体到两个圆心的距离:
[
d_1 = \sqrt{(x - x_1)^2 + (y - y_1)^2}, \quad d_2 = \sqrt{(x - x_2)^2 + (y - y_2)^2}
]
如果 ( d_1 ≤ r_1 ) 且 ( d_2 ≤ r_2 ),位置合法,无需调整。

2. 处理仅超出单个圆的情况

  • 若仅超出圆1(( d_1 > r_1 )):将位置沿 ( \mathbf{C_1} \to \mathbf{P} ) 的方向拉到圆1的边界:
    [
    \mathbf{P_{clamped}} = \mathbf{C_1} + \frac{\mathbf{P} - \mathbf{C_1}}{d_1} \times r_1
    ]
    由于两圆相切,这个拉回的点必然是切点(外切)或落在小圆内部(内切),一定符合圆2的约束。
  • 若仅超出圆2(( d_2 > r_2 )):同理,将位置拉到圆2的边界即可。

3. 处理同时超出两个圆的情况

这种情况仅发生在外切场景:物体位于两圆外侧,此时直接将位置钳制到两圆的切点 ( \mathbf{T} ),切点坐标计算:
[
\mathbf{T} = \mathbf{C_1} + \frac{\mathbf{C_2} - \mathbf{C_1}}{d} \times r_1
]
其中 ( d = r_1 + r_2 )(外切时的圆心距)。


伪代码实现

import math

def clamp_to_tangent_circles(pos, c1, r1, c2, r2):
    # 计算到两个圆心的距离(先算平方避免开根号,提升性能)
    dx1, dy1 = pos[0] - c1[0], pos[1] - c1[1]
    d1_sq = dx1**2 + dy1**2
    d1 = math.sqrt(d1_sq) if d1_sq > 0 else 0

    dx2, dy2 = pos[0] - c2[0], pos[1] - c2[1]
    d2_sq = dx2**2 + dy2**2
    d2 = math.sqrt(d2_sq) if d2_sq > 0 else 0

    # 检查是否在交集内(加微小值处理浮点误差)
    if d1 <= r1 + 1e-6 and d2 <= r2 + 1e-6:
        return pos

    # 拉回至圆1边界
    if d1 > r1:
        factor = r1 / d1
        clamped = (c1[0] + dx1 * factor, c1[1] + dy1 * factor)
        return clamped

    # 拉回至圆2边界
    if d2 > r2:
        factor = r2 / d2
        clamped = (c2[0] + dx2 * factor, c2[1] + dy2 * factor)
        return clamped

    # 外切场景下同时超出两圆,钳制到切点
    center_dx = c2[0] - c1[0]
    center_dy = c2[1] - c1[1]
    center_dist = math.sqrt(center_dx**2 + center_dy**2)
    tangent_factor = r1 / center_dist
    tangent_point = (c1[0] + center_dx * tangent_factor, c1[1] + center_dy * tangent_factor)
    return tangent_point

特殊场景补充

  • 外切情况:交集仅为切点,所有非法位置最终都会被钳制到该切点。
  • 内切情况:交集是整个小圆,此时只需按单个圆的钳制逻辑处理即可,因为小圆完全包含在大圆内,天然符合大圆的约束。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:27:11