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?