移动圆和固定线段之间的二维碰撞 [英] 2D collision between a moving circle and a fixed line segment

查看:26
本文介绍了移动圆和固定线段之间的二维碰撞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在游戏程序的上下文中,我有一个移动的圆和一个固定的线段.该段可以具有任意大小和方向.

In the context of a game program, I have a moving circle and a fixed line segment. The segment can have an arbitrary size and orientation.

  • 我知道圆的半径:r
  • 移动前我知道圆的坐标:(xC1, yC1)
  • 我知道移动后圆的坐标:(xC2, yC2)
  • 我知道线段末端的坐标:(xL1, yL1) - (xL2, yL2)

我在尝试计算时遇到困难:

I am having difficulties trying to compute:

  • 布尔值:如果圆的任何部分在从 (xC1, yC1) 移动到 (xC2, yC2) 时碰到线段
  • 如果布尔值为真,则圆心的坐标 (x, y) 当它碰到线段时(我的意思是圆第一次与线段相切时)
  • A boolean: If any part of the circle hits the line segment while moving from (xC1, yC1) to (xC2, yC2)
  • If the boolean is true, the coordinates (x, y) of the center of the circle when it hits the line segment (I mean when circle is tangent to segment for the first time)

推荐答案

看这里:

线段/圆交点

如果您在 x 或 y 计算的平方根下得到的值为负,则该线段不相交.除此之外,您可以在获得 x 和 y 后停止计算(注意:您可能会得到两个答案)

If the value you get under the square root of either the computation of x or y is negative, then the segment does not intersect. Aside from that, you can stop your computation after you have x and y (note: you may get two answers)

更新我已经修改了我的答案以非常具体地解决您的问题.我将此解决方案归功于 Doswa,因为我几乎紧随其后,为 C# 编写了它.基本策略是我们将定位线段的最接近圆心的点.在此基础上,我们将查看该最近点的距离,如果它在半径内,则沿着到位于圆半径处的最近点的方向定位该点.

Update I've revised my answer to very specifically address your problem. I give credit to Doswa for this solution, as I pretty much followed along and wrote it for C#. The basic strategy is that we are going to locate the closest point of your line segment to the center of the circle. Based on that, we'll look at the distance of that closest point, and if it is within the radius, locate the point along the direction to the closest point that lies right at the radius of the circle.

// I'll bet you already have one of these.
public class Vec : Tuple<double, double>
{
  public Vec(double item1, double item2) : base(item1, item2) { }
  public double Dot(Vec other) 
    { return Item1*other.Item1 + Item2*other.Item2; }
  public static Vec operator-(Vec first, Vec second) 
    { return new Vec(first.Item1 - second.Item1, first.Item2 - second.Item2);}
  public static Vec operator+(Vec first, Vec second) 
    { return new Vec(first.Item1 + second.Item1, first.Item2 + second.Item2);}
  public static Vec operator*(double first, Vec second) 
    { return new Vec(first * second.Item1, first * second.Item2);}
  public double Length() { return Math.Sqrt(Dot(this)); }
  public Vec Normalize() { return (1 / Length()) * this; }
}

public bool IntersectCircle(Vec origin, Vec lineStart, 
      Vec lineEnd, Vec circle, double radius, out Vec circleWhenHit)
{
    circleWhenHit = null;

    // find the closest point on the line segment to the center of the circle
    var line = lineEnd - lineStart;
    var lineLength = line.Length();
    var lineNorm = (1/lineLength)*line;
    var segmentToCircle = circle - lineStart;
    var closestPointOnSegment = segmentToCircle.Dot(line) / lineLength;

    // Special cases where the closest point happens to be the end points
    Vec closest;
    if (closestPointOnSegment < 0) closest = lineStart;
    else if (closestPointOnSegment > lineLength) closest = lineEnd;
    else closest = lineStart + closestPointOnSegment*lineNorm;

    // Find that distance.  If it is less than the radius, then we 
    // are within the circle
    var distanceFromClosest = circle - closest;
    var distanceFromClosestLength = distanceFromClosest.Length();
    if (distanceFromClosestLength > radius) return false;

    // So find the distance that places the intersection point right at 
    // the radius.  This is the center of the circle at the time of collision
    // and is different than the result from Doswa
    var offset = (radius - distanceFromClosestLength) *
                 ((1/distanceFromClosestLength)*distanceFromClosest);
    circleWhenHit = circle - offset;

    return true;
}

这篇关于移动圆和固定线段之间的二维碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆