in MREUnityRuntimeLib/ProceduralToolkit/Geometry/Distance2D.cs [881:976]
public static float SegmentCircle(Vector2 segmentA, Vector2 segmentB, Vector2 circleCenter, float circleRadius)
{
Vector2 segmentAToCenter = circleCenter - segmentA;
Vector2 fromAtoB = segmentB - segmentA;
float segmentLength = fromAtoB.magnitude;
if (segmentLength < Geometry.Epsilon)
{
return segmentAToCenter.magnitude - circleRadius;
}
Vector2 segmentDirection = fromAtoB.normalized;
float centerProjection = Vector2.Dot(segmentDirection, segmentAToCenter);
if (centerProjection + circleRadius < -Geometry.Epsilon ||
centerProjection - circleRadius > segmentLength + Geometry.Epsilon)
{
// No intersection
if (centerProjection < 0)
{
return segmentAToCenter.magnitude - circleRadius;
}
return (circleCenter - segmentB).magnitude - circleRadius;
}
float sqrDistanceToA = segmentAToCenter.sqrMagnitude;
float sqrDistanceToLine = sqrDistanceToA - centerProjection*centerProjection;
float sqrDistanceToIntersection = circleRadius*circleRadius - sqrDistanceToLine;
if (sqrDistanceToIntersection < -Geometry.Epsilon)
{
// No intersection
if (centerProjection < -Geometry.Epsilon)
{
return Mathf.Sqrt(sqrDistanceToA) - circleRadius;
}
if (centerProjection > segmentLength + Geometry.Epsilon)
{
return (circleCenter - segmentB).magnitude - circleRadius;
}
return Mathf.Sqrt(sqrDistanceToLine) - circleRadius;
}
if (sqrDistanceToIntersection < Geometry.Epsilon)
{
if (centerProjection < -Geometry.Epsilon)
{
// No intersection
return Mathf.Sqrt(sqrDistanceToA) - circleRadius;
}
if (centerProjection > segmentLength + Geometry.Epsilon)
{
// No intersection
return (circleCenter - segmentB).magnitude - circleRadius;
}
// Point intersection
return 0;
}
// Line intersection
float distanceToIntersection = Mathf.Sqrt(sqrDistanceToIntersection);
float distanceA = centerProjection - distanceToIntersection;
float distanceB = centerProjection + distanceToIntersection;
bool pointAIsAfterSegmentA = distanceA > -Geometry.Epsilon;
bool pointBIsBeforeSegmentB = distanceB < segmentLength + Geometry.Epsilon;
if (pointAIsAfterSegmentA && pointBIsBeforeSegmentB)
{
// Two points intersection
return 0;
}
if (!pointAIsAfterSegmentA && !pointBIsBeforeSegmentB)
{
// The segment is inside, but no intersection
distanceB = -(distanceB - segmentLength);
return distanceA > distanceB ? distanceA : distanceB;
}
bool pointAIsBeforeSegmentB = distanceA < segmentLength + Geometry.Epsilon;
if (pointAIsAfterSegmentA && pointAIsBeforeSegmentB)
{
// Point A intersection
return 0;
}
bool pointBIsAfterSegmentA = distanceB > -Geometry.Epsilon;
if (pointBIsAfterSegmentA && pointBIsBeforeSegmentB)
{
// Point B intersection
return 0;
}
// No intersection
if (centerProjection < 0)
{
return Mathf.Sqrt(sqrDistanceToA) - circleRadius;
}
return (circleCenter - segmentB).magnitude - circleRadius;
}