Algorithm 计算交叉口的高效数学算法

Algorithm 计算交叉口的高效数学算法,algorithm,math,performance,intersection,lines,Algorithm,Math,Performance,Intersection,Lines,对于我正在开发的一个游戏,我需要一个能够计算交点的算法。我已经解决了这个问题,但我的方式真的很糟糕,我希望这里的人能有一个更优雅的解决方案 一对点表示在它们之间绘制的直线的端点。给定两对点,绘制的线是否相交,如果相交,在哪一点 例如,调用行(A.x,A.y)-(B.x,B.y)和(C.x,C.y)-(D.x,D.y) 有人能想出解决办法吗?任何语言的解决方案都可以 编辑:一个我应该更清楚的点,如果交点超出线段长度,算法必须返回false。public struct PointD { 公共双X{g

对于我正在开发的一个游戏,我需要一个能够计算交点的算法。我已经解决了这个问题,但我的方式真的很糟糕,我希望这里的人能有一个更优雅的解决方案

一对点表示在它们之间绘制的直线的端点。给定两对点,绘制的线是否相交,如果相交,在哪一点

例如,调用行(A.x,A.y)-(B.x,B.y)和(C.x,C.y)-(D.x,D.y)

有人能想出解决办法吗?任何语言的解决方案都可以

编辑:一个我应该更清楚的点,如果交点超出线段长度,算法必须返回false。

public struct PointD
{
公共双X{get;set;}
公共双Y{get;set;}
}
/// 
///找到两条线之间的交点。
/// 
///交叉点。尖点结构。
///第一行的起点。尖点结构。
///第一行的终点。尖点结构。
///第二行的起点。尖点结构。
///第二行的终点。尖点结构。
///第一条线的交点位置。
///第二条直线的交点位置。
///返回一个布尔值。如果存在交点,则为True,否则为false。
///公式取自comp.graphics.algorithms常见问题解答。
公共静态布尔线相交(点D相交点、点D L1起始点、点D L1端点、点D L2起点、点D L2端点、点D双L1相交点、点D双L2相交点)
{
IntersectPoint=新点D();
双Y轴,ax轴,px轴,py轴;
双dx_cx=L2EndPoint.X-L2StartPoint.X,
dy_cy=L2EndPoint.Y-l2start.Y,
bx_ax=L1EndPoint.X-L1StartPoint.X,
by_ay=L1EndPoint.Y-L1StartPoint.Y;
双de=(bx x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x;
//双tor=1.0E-10;//公差
L1IntersectPos=0;L2IntersectPos=0;
if(Math.Abs(de)-tor&&de

要检查交点是否超出直线的原始长度,只需确保
0一个可以节省大量时间的简单优化是在进入交点计算之前检查直线的轴对齐边界框。
如果边界框完全不相交,则可以确定没有交点。
当然,这取决于您拥有的数据。如果在你做的每一次检查中都很可能出现交叉点,那么你可能会发现自己在一次总是正确的检查上浪费时间。

float x12=x1-x2;
float x12 = x1 - x2;
float x34 = x3 - x4;
float y12 = y1 - y2;
float y34 = y3 - y4;

float c = x12 * y34 - y12 * x34;

if (fabs(c) < 0.01)
{
  // No intersection
  return false;
}
else
{
  // Intersection
  float a = x1 * y2 - y1 * x2;
  float b = x3 * y4 - y3 * x4;

  float x = (a * x34 - b * x12) / c;
  float y = (a * y34 - b * y12) / c;

  return true;
}
浮动x34=x3-x4; 浮动y12=y1-y2; 浮动y34=y3-y4; 浮子c=x12*y34-y12*x34; if(晶圆厂(c)<0.01) { //无交叉路口 返回false; } 其他的 { //交叉口 浮点数a=x1*y2-y1*x2; 浮子b=x3*y4-y3*x4; 浮动x=(a*x34-b*x12)/c; 浮动y=(a*y34-b*y12)/c; 返回true; }
公式取自:

如果你有机会,如果你打算做任何非琐碎的事情,你应该真正查阅碰撞检测圣经“实时碰撞检测”。我不是一个专业的游戏程序员,我理解并能毫不费力地应用其中的概念

基本上,无论发生什么情况,进行一组线交点测试都是昂贵的。您要做的是在复杂多边形上使用边界框(轴对齐或定向)。这将允许您快速对每个“对象”之间的碰撞进行最坏情况O(N^2)检查。然后,通过使用空间树(二元分区或四叉树),只检查彼此接近的对象的交点,就可以进一步加快速度


这允许您删减很多很多碰撞测试。最好的优化是根本不做任何事情。只有当边界框之间发生碰撞时,才能进行昂贵的直线相交,以确定对象是否真正相交。这允许您在保持合理速度的同时扩大对象的数量。

好吧,数学和标量产品可以在这方面提供帮助。
-假设您要将段[AB]和[CD]相交
-假设两条直线的交点为M

当且仅当
向量(AB)。矢量(AM)>=0

向量(AB)。向量(MB)>=0

其中点“.”表示标量积:u。v=ux*vx+uy*vy

因此,您的算法是:
-查找M
-当且仅当以下4个等式为真时,M在两个段内
向量(AB)。矢量(AM)>=0
向量(AB)。向量(MB)>=0
向量(CD)。向量(CM)>=0
向量(CD)。向量(MD)>=0


希望这有帮助

下面是我的直线交点,如中所述。对于一般碰撞检测/交叉点,您可能需要查看。我发现SAT上的内容非常丰富

    /// <summary>
    /// Returns the intersection point of the given lines. 
    /// Returns Empty if the lines do not intersect.
    /// Source: http://mathworld.wolfram.com/Line-LineIntersection.html
    /// </summary>
    public static PointF LineIntersection(PointF v1, PointF v2, PointF v3, PointF v4)
    {
        float tolerance = 0.000001f;

        float a = Det2(v1.X - v2.X, v1.Y - v2.Y, v3.X - v4.X, v3.Y - v4.Y);
        if (Math.Abs(a) < float.Epsilon) return PointF.Empty; // Lines are parallel

        float d1 = Det2(v1.X, v1.Y, v2.X, v2.Y);
        float d2 = Det2(v3.X, v3.Y, v4.X, v4.Y);
        float x = Det2(d1, v1.X - v2.X, d2, v3.X - v4.X) / a;
        float y = Det2(d1, v1.Y - v2.Y, d2, v3.Y - v4.Y) / a;

        if (x < Math.Min(v1.X, v2.X) - tolerance || x > Math.Max(v1.X, v2.X) + tolerance) return PointF.Empty;
        if (y < Math.Min(v1.Y, v2.Y) - tolerance || y > Math.Max(v1.Y, v2.Y) + tolerance) return PointF.Empty;
        if (x < Math.Min(v3.X, v4.X) - tolerance || x > Math.Max(v3.X, v4.X) + tolerance) return PointF.Empty;
        if (y < Math.Min(v3.Y, v4.Y) - tolerance || y > Math.Max(v3.Y, v4.Y) + tolerance) return PointF.Empty;

        return new PointF(x, y);
    }

    /// <summary>
    /// Returns the determinant of the 2x2 matrix defined as
    /// <list>
    /// <item>| x1 x2 |</item>
    /// <item>| y1 y2 |</item>
    /// </list>
    /// </summary>
    public static float Det2(float x1, float x2, float y1, float y2)
    {
        return (x1 * y2 - y1 * x2);
    }
//
///返回给定直线的交点。
///如果两条线不相交,则返回空。
///资料来源:http://mathworld.wolfram.com/Line-LineIntersection.html
/// 
公共静态点F线交点(点F v1、点F v2、点F v3、点F v4)
{
浮动公差=0.000001f;
float a=Det2(v1.X-v2.X,v1.Y-v2.Y,v3.X-v4.X,v3.Y-v4.Y);
if(Math.Abs(a)private function Loop(e:Event):void
{
    var x12:Number = Ball1.x - Ball2.x;
    var x34:Number = Ball3.x - Ball4.x;
    var y12:Number = Ball1.y - Ball2.y;
    var y34:Number = Ball3.y - Ball4.y;

    // Det
    var c:Number = x12 * y34 - y12 * x34;

    if (Math.abs(c) < 0.01)
    {
        Circle.visible = false;
    }
    else
    {
        var a:Number = Ball1.x * Ball2.y - Ball1.y * Ball2.x;
        var b:Number = Ball3.x * Ball4.y - Ball3.y * Ball4.x;
        var px:Number = (a * x34 - b * x12) / c;
        var py:Number = (a * y34 - b * y12) / c;

        var Btwn12x:Boolean = (px >= Math.min(Ball1.x, Ball2.x)) && (px <= Math.max(Ball1.x, Ball2.x));
        var Btwn12y:Boolean = (py >= Math.min(Ball1.y, Ball2.y)) && (py <= Math.max(Ball1.y, Ball2.y));
        var Btwn34x:Boolean = (px >= Math.min(Ball3.x, Ball4.x)) && (px <= Math.max(Ball3.x, Ball4.x));
        var Btwn34y:Boolean = (py >= Math.min(Ball3.y, Ball4.y)) && (py <= Math.max(Ball3.y, Ball4.y));

        var Btwn12:Boolean = Btwn12x && Btwn12y;
        var Btwn34:Boolean = Btwn34x && Btwn34y;

        if(Btwn12 && Btwn34)
        {
            Circle.visible = true;
            Circle.x = px;
            Circle.y = py;
        }
        else
        {
            Circle.visible = false;
        }
    }
}