Смотрите здесь:
Сегмент линии / пересечение окружности
Если значение, которое вы получите под квадратным корнем из вычисления x или y, является отрицательным, то сегмент не пересекается. Кроме того, вы можете остановить вычисления после того, как у вас есть x и y (примечание: вы можете получить два ответа)
Обновление Я пересмотрел свой ответ, чтобы очень конкретно решить вашу проблему. Я отдаю должное Doswa за это решение, так как я довольно много последовал и написал его для C #. Основная стратегия заключается в том, что мы собираемся расположить ближайшую точку вашего отрезка к центру круга. Исходя из этого, мы посмотрим на расстояние этой ближайшей точки, и, если оно находится в радиусе, найдите точку вдоль направления к ближайшей точке, которая лежит прямо на радиусе круга.
// I'll bet you already have one of these.
public class Vec : Tuple<double, double>
{
public Vec(double item1, double item2) : base(item1, item2) { }
public double Dot(Vec other)
{ return Item1*other.Item1 + Item2*other.Item2; }
public static Vec operator-(Vec first, Vec second)
{ return new Vec(first.Item1 - second.Item1, first.Item2 - second.Item2);}
public static Vec operator+(Vec first, Vec second)
{ return new Vec(first.Item1 + second.Item1, first.Item2 + second.Item2);}
public static Vec operator*(double first, Vec second)
{ return new Vec(first * second.Item1, first * second.Item2);}
public double Length() { return Math.Sqrt(Dot(this)); }
public Vec Normalize() { return (1 / Length()) * this; }
}
public bool IntersectCircle(Vec origin, Vec lineStart,
Vec lineEnd, Vec circle, double radius, out Vec circleWhenHit)
{
circleWhenHit = null;
// find the closest point on the line segment to the center of the circle
var line = lineEnd - lineStart;
var lineLength = line.Length();
var lineNorm = (1/lineLength)*line;
var segmentToCircle = circle - lineStart;
var closestPointOnSegment = segmentToCircle.Dot(line) / lineLength;
// Special cases where the closest point happens to be the end points
Vec closest;
if (closestPointOnSegment < 0) closest = lineStart;
else if (closestPointOnSegment > lineLength) closest = lineEnd;
else closest = lineStart + closestPointOnSegment*lineNorm;
// Find that distance. If it is less than the radius, then we
// are within the circle
var distanceFromClosest = circle - closest;
var distanceFromClosestLength = distanceFromClosest.Length();
if (distanceFromClosestLength > radius) return false;
// So find the distance that places the intersection point right at
// the radius. This is the center of the circle at the time of collision
// and is different than the result from Doswa
var offset = (radius - distanceFromClosestLength) *
((1/distanceFromClosestLength)*distanceFromClosest);
circleWhenHit = circle - offset;
return true;
}