Here's an extension I added to the vertices class to figure out which edge is the closest to a given point:
public int GetClosestEdge(Vector2 point)
int closest = -1;
float lowestDistance = float.MaxValue;
for (int i = 0; i < this.Count; i++)
var diff = point - this[i];
var dist = diff.LengthSquared();
if (dist < lowestDistance)
lowestDistance = dist;
closest = i;
var p = this[closest];
var edge1 = GetEdge(closest);
edge1 = p + edge1;
var edge2 = -GetEdge(PreviousIndex(closest));
edge2 = p + edge2;
if ((point - edge1).LengthSquared() < (point - edge2).LengthSquared())
Basically it works by first finding the closest vertex to the given point. Once you have that it needs to make a choice whether to take the edge leading to that vertex or the edge leading away. The way it makes a choice is to calculate the point along each
edge that is one unit away from the closest vertex; whichever point is closer the given point is chosen as the closest edge.
This may not be the most optimal way of finding the closest edge to a point, but I gave up trying to get the contact list in OnCollision to produce any meaningful results. Sometimes it would use vertexes in one polygon, sometimes in the other; most of the
time the vertex index it would return is an invalid index and doesn't belong to either of the polygons involved in the collision.
So basically I do this:
int edge = body2.WorldVertices.GetClosestEdge(contactList.Positon);
And in all my tests it seems to get the edge that the collision occurred on.