Get the collision side of colliding rectangles

21 views Asked by At

I use simple C# System.Drawing graphics and want to check if two polygons are colliding. I already have some (more or less) working code.

public bool Collide(PointF[] a, PointF[] b)
{
    List<PointF> self = a.ToList();
    List<PointF> other = b.ToList();

    return PolygonIntersectsPolygon(self, other)
        || PolygonIntersectsPolygon(other, self);
}

public bool PolygonIntersectsPolygon(List<PointF> polygonA, List<PointF> polygonB)
{
    int countA = polygonA.Count;
    int countB = polygonB.Count;

    for (int i = 0; i < countA; i++)
    {
        PointF p1 = polygonA[i];
        PointF p2 = polygonA[(i + 1) % countA];

        if (LineIntersectsPolygon(p1, p2, polygonB))
        {
            return true;
        }
    }

    return false;
}

public bool LineIntersectsPolygon(PointF p1, PointF p2, List<PointF> polygon)
{
    int count = polygon.Count;

    for (int i = 0; i < count; i++)
    {
        PointF q1 = polygon[i];
        PointF q2 = polygon[(i + 1) % count];

        if (LineIntersectsLine(p1, p2, q1, q2))
        {
            return true;
        }
    }

    return false;
}

public bool LineIntersectsLine(PointF p1, PointF p2, PointF q1, PointF q2)
{
    int o1 = Orientation(p1, p2, q1);
    int o2 = Orientation(p1, p2, q2);
    int o3 = Orientation(q1, q2, p1);
    int o4 = Orientation(q1, q2, p2);

    if (o1 != o2 && o3 != o4)
    {
        return true;
    }

    if (o1 == 0 && OnSegment(p1, q1, p2)) return true;
    if (o2 == 0 && OnSegment(p1, q2, p2)) return true;
    if (o3 == 0 && OnSegment(q1, p1, q2)) return true;
    if (o4 == 0 && OnSegment(q1, p2, q2)) return true;

    return false;
}

public int Orientation(PointF p, PointF q, PointF r)
{
    float val = (q.Y - p.Y) * (r.X - q.X) - (q.X - p.X) * (r.Y - q.Y);
    if (val == 0) return 0;
    return (val > 0) ? 1 : 2;
}

public bool OnSegment(PointF p, PointF q, PointF r)
{
    return q.X <= Math.Max(p.X, r.X) && q.X >= Math.Min(p.X, r.X) &&
           q.Y <= Math.Max(p.Y, r.Y) && q.Y >= Math.Min(p.Y, r.Y);
}

The problem is that i cant figure out how to detect the side on which the collision occures. I tried it using this method

public string GetCollisionSide(PointF p1, PointF p2, PointF q1, PointF q2)
{
    float crossProduct = (p2.X - p1.X) * (q2.Y - q1.Y) - (p2.Y - p1.Y) * (q2.X - q1.X);

    if (Math.Abs(crossProduct) < float.Epsilon)
    {
        // Linien sind parallel, keine Kollision
        return "None";
    }

    float dotProduct = (p2.X - p1.X) * (q2.X - q1.X) + (p2.Y - p1.Y) * (q2.Y - q1.Y);

    if (dotProduct < 0)
    {
        return "Left";
    }

    float squaredLengthQ1Q2 = (q2.X - q1.X) * (q2.X - q1.X) + (q2.Y - q1.Y) * (q2.Y - q1.Y);
    if (dotProduct > squaredLengthQ1Q2)
    {
        return "Right";
    }

    if (crossProduct > 0)
    {
        return "Top";
    }

    return "Bottom";
}

But when a polygon drives into a corner having x- any y-axis the same speed the result is not accurate. How can i detect the side of the collision?

0

There are 0 answers