# Polygon 2D collision response- How do I find the correct edge a polygon hit?

Hey guys I've been seriously stressed out by this, so please go easy on me.

My goal is to reflect a bullet (polygon) off of another polygon, and find the edge the another polygon, A (the bullet), hit. The collision code below partially works, thanks to this. I modified it a little to embed it into my code. The problem I'm facing is that the code below does not give me the edge of the polygon that the bullet hit. Through many resources like this, I was able to figure out the math behind what is presented in the picture below. I've done a lots of research, and am aware of the SAT, but am unable to extract the correct edge the projectile hit based off of the code.

Note that the picture presented has only rectangles, but this is aimed to work on all non-concave polygons. I feel there's a fundamental understanding I'm missing, and not spotting it in the code, more specifically in the loops. To be clear, how am I able to modify the code below to return results where the bullet may act appropriately?

public class MainForm {

// Structure that stores the results of the PolygonCollision function
public struct PolygonCollisionResult {
public bool Intersect; // Are the polygons currently intersecting
public Vector NormalForceVector;
}

// Check if polygon A is going to collide with polygon B for the given velocity
public static PolygonCollisionResult PolygonCollision(Polygon polygonA, Polygon polygonB, Vector velocity) {
var result = new PolygonCollisionResult
{
Intersect = true
};

int edgeCountA = polygonA.Edges.Count;
int edgeCountB = polygonB.Edges.Count;

Vector[] edgesVectors = new Vector[edgeCountA + edgeCountB];

//adds all edges to an array
for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
{
if (edgeIndex < edgeCountA)
edgesVectors[edgeIndex] = polygonA.Edges[edgeIndex];
else
edgesVectors[edgeIndex] = polygonB.Edges[edgeIndex - edgeCountA];

}

// Loop through all the edges of both polygons
foreach(var edge in edgesVectors)
{

// Find the axis perpendicular to the current edge
Vector axis = new Vector(-edge.Y, edge.X);
axis.Normalize();

// Find the projection of the polygon on the current axis
float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
ProjectPolygon(axis, polygonA, ref minA, ref maxA);
ProjectPolygon(axis, polygonB, ref minB, ref maxB);

// Check if the polygon projections are currentlty intersecting
if (IntervalDistance(minA, maxA, minB, maxB) > 0)
result.Intersect = false;

// If the polygons are not intersecting, exit the loop
if (!result.Intersect)
break;

//I need to return the edge hit and assign it to NormalForceVector
result.NormalForceVector.X = ?????????;
result.NormalForceVector.Y = ?????????;

}

return result;
}

//Two helper methods below that work perfectly fine:

// Calculate the distance between [minA, maxA] and [minB, maxB]
// The distance will be negative if the intervals overlap
public static float IntervalDistance(float minA, float maxA, float minB, float maxB)
{
if (minA < minB)
return minB - maxA;

return minA - maxB;
}

// Calculate the projection of a polygon on an axis and returns it as a [min, max] interval
public static void ProjectPolygon(Vector axis, Polygon polygon, ref float min, ref float max)
{
// To project a point on an axis use the dot product
float d = axis.DotProduct(polygon.Points);
min = d;
max = d;
for (int i = 0; i < polygon.Points.Count; i++)
{
d = polygon.Points[i].DotProduct(axis);
if (d < min)
{
min = d;
}
else
{
if (d > max)
{
max = d;
}
}
}
}
}


This loop here is where I'm cycling through all of the polygons, checking for collision.

foreach (var polyEntity in RunGame.Level.ObjListPolygon)
{

var resultStruct = MainForm.PolygonCollision(_bulletPolygon, polyEntity, new Vector(_velocity.X, _velocity.Y));

if (resultStruct.Intersect)
{

//here is where i'm using that normal force
var normalForce = new Vector2(resultStruct.NormalForceVector.X, resultStruct.NormalForceVector.Y);
normalForce.Normalize();

_velocity = Vector2.Reflect(_velocity, normalForce);

_angle = (float)Math.Atan2(_velocity.Y, _velocity.X);

break;
}
}


From debugging, I know that the foreach loop where it iterates through each polygon edge returns the last edge in the loop. Because this code returns that edge (which it should not), I'm only gaining sufficient results for that edge. In the future, my goal is to add not only polygons, but circles/ellipses as well (in the far future). Does anyone know what's going wrong? Anything helps.

• Please comment if anything is unclear, or if more information is needed. Thanks! – Eric Jul 14 '16 at 4:18