首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >接触点:圆碰撞

接触点:圆碰撞
EN

Stack Overflow用户
提问于 2013-03-09 07:06:49
回答 3查看 1.3K关注 0票数 1

我正在做一个关于机器人世界杯的学校项目,机器人和人工智能一起踢足球。虽然一切正常,但我还是被一些东西卡住了。

机器人是从俯视图绘制的简单球体。两个玩家都不应该被允许走进对方,并且应该在撞击点上得到一个新的更新位置。

因为冲突处理程序只检查它们是否冲突。我希望能不能找到一种方法来检测圆圈的碰撞位置。因此,我可以将碰撞球体的位置更新到最后已知的非碰撞位置,这样它们就不会相互穿行,可能会弹开。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-03-09 07:15:47

您需要做的是找到两个圆之间的交点,交点可以是两个点、一个点或没有交点。这基本上是通过一起求解两个圆的方程来完成的。数学是这样的:

http://www.analyzemath.com/CircleEq/circle_intersection.html

由于这是为学校编写的,我将把代码留给您:)

票数 0
EN

Stack Overflow用户

发布于 2013-03-09 07:15:22

圆的圆周上的所有点都是距圆中心的距离,半径是相同的。这对运动场上的每一个圈子都是正确的。

因此:当两个圆的中心之间的距离等于它们尊重的半径之和时,它们就完全相撞了。( <= )

票数 2
EN

Stack Overflow用户

发布于 2013-03-09 07:56:41

好了,你已经标记了答案,但是我把一个功能齐全的代码放在了一起,所以也许你无论如何都可以使用它。:)来自我的评论:

因为它们只是圆,所以只需计算圆的中心点之间的中点。如果圆的半径不同,则选择一个圆,并沿距其中心一个半径的直线计算点。

这可能是一个简单的实现。我为它创建了一些非常简陋的帮助器类;我完全鼓励扩展它们,使结构真正不可变,以及所有那些好的jazz,但现在可以用于演示目的。

所以对于帮助器类:

代码语言:javascript
复制
public struct Point
{
    public double X;
    public double Y;

    public double Distance(Point otherPoint)
    {
        double deltaX = this.X - otherPoint.X;
        double deltaY = this.Y - otherPoint.Y;
        return System.Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
    }

    public override string ToString()
    {
        return String.Format("({0}, {1})", X, Y);
    }
}

public struct Polar
{
    public double Radius;
    public double Angle;

    public double X { get { return Radius * System.Math.Cos(Angle); } }
    public double Y { get { return Radius * System.Math.Sin(Angle); } }

    public Point ToCartesian()
    {
        return new Point() { X = X, Y = Y };
    }
}

public class Circle
{
    public double Radius { get; set; }
    public Point Position { get; set; }
}

我们的简单类/方法如下:

代码语言:javascript
复制
public class CollisionResult
{
    public Circle Circle1 { get; private set; }
    public Circle Circle2 { get; private set; }

    public Point Circle1SafeLocation { get; private set; }
    public Point Circle2SafeLocation { get; private set; }

    public Point CollisionLocation { get; private set; }

    public CollisionResult(Circle circle1, Circle circle2)
    {
        this.Circle1 = circle1;
        this.Circle2 = circle2;
    }

    public bool CalculateCollision()
    {
        double distanceFromCentres = Circle1.Position.Distance(Circle2.Position);
        if (distanceFromCentres >= Circle1.Radius + Circle2.Radius)
            return false;

        double angleBetweenCircles = System.Math.Atan2(Circle2.Position.Y - Circle1.Position.Y, Circle2.Position.X - Circle1.Position.X);

        Point midpointBetweenCircles = new Point(){X = (Circle1.Position.X + Circle2.Position.X)/2, Y = (Circle1.Position.Y + Circle2.Position.Y)/2};

        Point circle1Offset = (new Polar() { Radius = Circle1.Radius, Angle = System.Math.PI + angleBetweenCircles }).ToCartesian();
        Point circle2Offset = (new Polar() { Radius = Circle2.Radius, Angle = angleBetweenCircles }).ToCartesian();

        CollisionLocation = midpointBetweenCircles;
        Circle1SafeLocation = new Point(){X = midpointBetweenCircles.X + circle1Offset.X, Y = midpointBetweenCircles.Y + circle1Offset.Y };
        Circle2SafeLocation = new Point(){X = midpointBetweenCircles.X + circle2Offset.X, Y = midpointBetweenCircles.Y + circle2Offset.Y };

        return true;
    }
}

用法可能如下所示:

代码语言:javascript
复制
private void CheckCollision(Circle circle1, Circle circle2)
{
    CollisionResult result = new CollisionResult(circle1, circle2);
    if (result.CalculateCollision())
    {
        Console.WriteLine(String.Format("Collision detected at {0}! Safe location for circle 1: {1}, circle 2: {2}", result.CollisionLocation, result.Circle1SafeLocation, result.Circle2SafeLocation));
    }
    else
    {
        Console.WriteLine("Did not collide.");
    }
}

var circle1 = new Circle() {Radius = 5, Position = new Point(){X = 0, Y = 0} };
var circle2 = new Circle() {Radius = 5, Position = new Point(){X = 10, Y = 0} };
var circle3 = new Circle() {Radius = 3, Position = new Point(){X = 0, Y = 1} };
var circle4 = new Circle() {Radius = 5, Position = new Point(){X = 3, Y = 7} };

CheckCollision(circle1, circle2);
CheckCollision(circle3, circle4);

输出:

代码语言:javascript
复制
Did not collide.
Collision detected at (1.5, 4)! Safe location for circle 1: (0.158359213500125, 1.31671842700025), circle 2: (3.73606797749979, 8.47213595499958)

我不知道在你的例子中,是否有必要处理计算两个圆的真实交点(它们将在两个点相交)之类的复杂问题。很可能这些东西对你来说就足够了。我绝对鼓励进行健康的单元测试,并使这些类比我在这里所拥有的更合适。:)

编辑:在这种情况下,很重要的一点是,当圆重叠时,它只是计算它们之间的中点,然后将每个圆从该中点移开各自的半径,这将取决于您想要为应用程序做什么。因此,根据圆圈的速度和大小,或者它们的移动方式,它可能会产生奇怪的结果。例如,如果你有一个半径为10的大圆静止不动,那么你抛出一个半径为1的圆,距离大圆的中心只有0.5个距离,这个大圆将移动大约9.75个单位!如果你没有遇到很大的重叠条件,那么这可能不是什么大问题。我认为这至少会给你一些关于碰撞的信息,然后你希望你的圆圈如何反应,这将取决于你。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15304858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档