public static void SegmentCircle()

in MREUnityRuntimeLib/ProceduralToolkit/Geometry/Closest2D.cs [1144:1283]


		public static void SegmentCircle(Vector2 segmentA, Vector2 segmentB, Vector2 circleCenter, float circleRadius,
			out Vector2 segmentPoint, out Vector2 circlePoint)
		{
			Vector2 segmentAToCenter = circleCenter - segmentA;
			Vector2 fromAtoB = segmentB - segmentA;
			float segmentLength = fromAtoB.magnitude;
			if (segmentLength < Geometry.Epsilon)
			{
				segmentPoint = segmentA;
				float distanceToPoint = segmentAToCenter.magnitude;
				if (distanceToPoint < circleRadius + Geometry.Epsilon)
				{
					if (distanceToPoint > circleRadius - Geometry.Epsilon)
					{
						circlePoint = segmentPoint;
						return;
					}
					if (distanceToPoint < Geometry.Epsilon)
					{
						circlePoint = segmentPoint;
						return;
					}
				}
				Vector2 toPoint = -segmentAToCenter/distanceToPoint;
				circlePoint = circleCenter + toPoint*circleRadius;
				return;
			}

			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)
				{
					segmentPoint = segmentA;
					circlePoint = circleCenter - segmentAToCenter.normalized*circleRadius;
					return;
				}
				segmentPoint = segmentB;
				circlePoint = circleCenter - (circleCenter - segmentB).normalized*circleRadius;
				return;
			}

			float sqrDistanceToLine = segmentAToCenter.sqrMagnitude - centerProjection*centerProjection;
			float sqrDistanceToIntersection = circleRadius*circleRadius - sqrDistanceToLine;
			if (sqrDistanceToIntersection < -Geometry.Epsilon)
			{
				// No intersection
				if (centerProjection < -Geometry.Epsilon)
				{
					segmentPoint = segmentA;
					circlePoint = circleCenter - segmentAToCenter.normalized*circleRadius;
					return;
				}
				if (centerProjection > segmentLength + Geometry.Epsilon)
				{
					segmentPoint = segmentB;
					circlePoint = circleCenter - (circleCenter - segmentB).normalized*circleRadius;
					return;
				}
				segmentPoint = segmentA + segmentDirection*centerProjection;
				circlePoint = circleCenter + (segmentPoint - circleCenter).normalized*circleRadius;
				return;
			}

			if (sqrDistanceToIntersection < Geometry.Epsilon)
			{
				if (centerProjection < -Geometry.Epsilon)
				{
					// No intersection
					segmentPoint = segmentA;
					circlePoint = circleCenter - segmentAToCenter.normalized*circleRadius;
					return;
				}
				if (centerProjection > segmentLength + Geometry.Epsilon)
				{
					// No intersection
					segmentPoint = segmentB;
					circlePoint = circleCenter - (circleCenter - segmentB).normalized*circleRadius;
					return;
				}
				// Point intersection
				segmentPoint = circlePoint = segmentA + segmentDirection*centerProjection;
				return;
			}

			// 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)
			{
				segmentPoint = circlePoint = segmentA + segmentDirection*distanceA;
				return;
			}
			if (!pointAIsAfterSegmentA && !pointBIsBeforeSegmentB)
			{
				// The segment is inside, but no intersection
				if (distanceA > -(distanceB - segmentLength))
				{
					segmentPoint = segmentA;
					circlePoint = segmentA + segmentDirection*distanceA;
					return;
				}
				segmentPoint = segmentB;
				circlePoint = segmentA + segmentDirection*distanceB;
				return;
			}

			bool pointAIsBeforeSegmentB = distanceA < segmentLength + Geometry.Epsilon;
			if (pointAIsAfterSegmentA && pointAIsBeforeSegmentB)
			{
				// Point A intersection
				segmentPoint = circlePoint = segmentA + segmentDirection*distanceA;
				return;
			}
			bool pointBIsAfterSegmentA = distanceB > -Geometry.Epsilon;
			if (pointBIsAfterSegmentA && pointBIsBeforeSegmentB)
			{
				// Point B intersection
				segmentPoint = circlePoint = segmentA + segmentDirection*distanceB;
				return;
			}

			// No intersection
			if (centerProjection < 0)
			{
				segmentPoint = segmentA;
				circlePoint = circleCenter - segmentAToCenter.normalized*circleRadius;
				return;
			}
			segmentPoint = segmentB;
			circlePoint = circleCenter - (circleCenter - segmentB).normalized*circleRadius;
		}