private bool Intersects(CollisionCircle circle)
{
float radiusSquared = circle.Radius * circle.Radius;
var vertex = GetWorldPosition(Vertices[Vertices.Count - 1]);
var circleCenter = circle.GetCenter();
float nearestDistance = float.MaxValue;
bool nearestIsInside = false;
int nearestVertex = -1;
bool lastIsInside = false;
for (int i = 0; i < Vertices.Count; i++)
{
var nextVertex = GetWorldPosition(Vertices[i]);
var axis = circleCenter - vertex;
float distance = axis.LengthSquared() - radiusSquared;
if (distance <= 0)
return true;
bool isInside = false;
var edge = nextVertex - vertex;
float edgeLengthSquared = edge.LengthSquared();
if (!edgeLengthSquared.Equals(0))
{
float dot = Vector2.Dot(edge, axis);
if (dot >= 0 && dot <= edgeLengthSquared)
{
var projection = vertex + (dot / edgeLengthSquared) * edge;
axis = projection - circleCenter;
if (axis.LengthSquared() <= radiusSquared)
return true;
if (edge.X > 0)
{
if (axis.Y > 0)
return false;
}
else if (edge.X < 0)
{
if (axis.Y < 0)
return false;
}
else if (edge.Y > 0)
{
if (axis.X < 0)
return false;
}
else
{
if (axis.X > 0)
return false;
}
isInside = true;
}
}
if (distance < nearestDistance)
{
nearestDistance = distance;
nearestIsInside = isInside || lastIsInside;
nearestVertex = i;
}
vertex = nextVertex;
lastIsInside = isInside;
}
if (nearestVertex == 0)
return nearestIsInside || lastIsInside;
return nearestIsInside;
}