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

移动圆与静止圆碰撞检测:求解碰撞交点及Java实现

移动圆与静止圆的碰撞点计算方案与Java实现

数学推导

你列出的方程可以整理为标准二次方程求解参数t,步骤如下:

  1. 定义辅助向量:
    • D = S - P:移动圆起点到静止圆圆心的向量
    • V = End - S:移动圆的位移向量
  2. 展开并整理碰撞条件方程:
    原方程 (Ra+Rb)² = |P - (S + tV)|² 等价于 (Ra+Rb)² = |(S - P) + tV|²,展开后得到:
    |V|² * t² + 2*(D·V)*t + (|D|² - (Ra+Rb)²) = 0
    
    这是标准的a*t² + b*t + c = 0形式,其中:
    • a = V.x² + V.y²
    • b = 2*(D.x*V.x + D.y*V.y)
    • c = (D.x² + D.y²) - (Ra + Rb)*(Ra + Rb)
  3. 求解二次方程:
    • 计算判别式delta = b² - 4*a*c:
      • 若delta < 0:无实根,两圆在移动路径内无碰撞,返回目标点End
      • 若delta >= 0:计算两个根t1 = [-b - sqrt(delta)]/(2*a),t2 = [-b + sqrt(delta)]/(2*a)(t1 <= t2)
  4. 筛选有效t值:
    只有当t在[0,1]区间内时,碰撞点才落在移动圆的起点到终点路径上。取最小的符合条件的t值,计算碰撞点C = S + t*V;若没有符合条件的t,返回目标点End

Java代码实现

首先定义表示点的类:

class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    // 用于计算点的加法与数乘
    public Point add(Point other) {
        return new Point(this.x + other.x, this.y + other.y);
    }

    public Point multiply(double scalar) {
        return new Point(this.x * scalar, this.y * scalar);
    }
}

然后实现核心计算函数:

public class CircleCollision {
    public static Point calculateCollisionPoint(Point startS, Point end, Point staticP, double ra, double rb) {
        // 计算位移向量V
        Point V = new Point(end.x - startS.x, end.y - startS.y);
        // 计算向量D = S - P
        Point D = new Point(startS.x - staticP.x, startS.y - staticP.y);

        double a = V.x * V.x + V.y * V.y;
        // 若移动向量长度为0(起点等于终点),直接返回起点
        if (a == 0) {
            return startS;
        }

        double b = 2 * (D.x * V.x + D.y * V.y);
        double sumRadii = ra + rb;
        double c = (D.x * D.x + D.y * D.y) - sumRadii * sumRadii;

        double delta = b * b - 4 * a * c;
        // 无实根,无碰撞
        if (delta < 0) {
            return end;
        }

        double sqrtDelta = Math.sqrt(delta);
        double t1 = (-b - sqrtDelta) / (2 * a);
        double t2 = (-b + sqrtDelta) / (2 * a);

        // 寻找符合0<=t<=1的最小t
        double validT = Double.MAX_VALUE;
        if (t1 >= 0 && t1 <= 1) {
            validT = t1;
        }
        if (t2 >= 0 && t2 <= 1 && t2 < validT) {
            validT = t2;
        }

        // 没有有效t,返回终点
        if (validT == Double.MAX_VALUE) {
            return end;
        }

        // 计算碰撞点
        return startS.add(V.multiply(validT));
    }

    // 测试示例
    public static void main(String[] args) {
        Point start = new Point(0, 0);
        Point end = new Point(10, 0);
        Point staticCircle = new Point(5, 0);
        double ra = 1;
        double rb = 1;

        Point collisionPoint = calculateCollisionPoint(start, end, staticCircle, ra, rb);
        System.out.println("碰撞点坐标:(" + collisionPoint.x + ", " + collisionPoint.y + ")");
    }
}

代码说明

  • 处理了移动向量为0的特殊情况(起点与终点重合)
  • 严格筛选t的有效范围,确保碰撞点落在移动路径内
  • 优先取更小的t值,保证返回的是靠近起点的碰撞点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 03:20:17