Skip to content

Commit

Permalink
remove tail recursion form welzl
Browse files Browse the repository at this point in the history
  • Loading branch information
OliBomby committed Sep 24, 2024
1 parent 3031b68 commit 2d95c0b
Showing 1 changed file with 25 additions and 21 deletions.
46 changes: 25 additions & 21 deletions osu.Game/Utils/GeometryUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,33 +305,37 @@ private static (Vector2, float) minCircleTrivial(ReadOnlySpan<Vector2> points)
// n represents the number of points in P that are not yet processed.
private static (Vector2, float) welzlHelper(List<Vector2> points, ReadOnlySpan<Vector2> r, int n)
{
// Base case when all points processed or |R| = 3
if (n == 0 || r.Length == 3)
return minCircleTrivial(r);
Span<Vector2> r2 = stackalloc Vector2[3];
int rLength = r.Length;
r.CopyTo(r2);

// Pick a random point randomly
int idx = RNG.Next(n);
Vector2 p = points[idx];
while (true)
{
// Base case when all points processed or |R| = 3
if (n == 0 || rLength == 3) return minCircleTrivial(r2[..rLength]);

// Put the picked point at the end of P since it's more efficient than
// deleting from the middle of the list
(points[idx], points[n - 1]) = (points[n - 1], points[idx]);
// Pick a random point randomly
int idx = RNG.Next(n);
Vector2 p = points[idx];

// Get the MEC circle d from the set of points P - {p}
var d = welzlHelper(points, r, n - 1);
// Put the picked point at the end of P since it's more efficient than
// deleting from the middle of the list
(points[idx], points[n - 1]) = (points[n - 1], points[idx]);

// If d contains p, return d
if (isInside(d, p))
return d;
// Get the MEC circle d from the set of points P - {p}
var d = welzlHelper(points, r2[..rLength], n - 1);

// Otherwise, must be on the boundary of the MEC
// Stackalloc to avoid allocations. It's safe to assume that the length of r will be at most 3
Span<Vector2> r2 = stackalloc Vector2[r.Length + 1];
r.CopyTo(r2);
r2[r.Length] = p;
// If d contains p, return d
if (isInside(d, p)) return d;

// Return the MEC for P - {p} and R U {p}
return welzlHelper(points, r2, n - 1);
// Otherwise, must be on the boundary of the MEC
// Stackalloc to avoid allocations. It's safe to assume that the length of r will be at most 3
r2[rLength] = p;
rLength++;

// Return the MEC for P - {p} and R U {p}
n--;
}
}

#endregion
Expand Down

0 comments on commit 2d95c0b

Please sign in to comment.