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

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

问题描述

在一个游戏程序的情况下,我有一个移动圈和固定线段。该段可以具有任意的大小和方向。

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.

  • 在我所知道的圆的半径为研究
  • 我知道在移动之前圆的坐标:(XC1,YC1)
  • 我知道搬家后圆的坐标:(XC2,YC2)
  • 我知道线段的末端的坐标:(XL1,YL1) - (XL2,YL2)
  • I know the radius of the circle: r
  • I know the coordinates of the circle before the move: (xC1, yC1)
  • I know the coordinates of the circle after the move: (xC2, yC2)
  • I know the coordinates of the extremities of the line segment: (xL1, yL1) - (xL2, yL2)

我有困难,试图计算:

  • 一个布尔:如果部分圈打线段,而从(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 此解决方案,因为我pretty的多其次沿线和写的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;
}

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

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