Enclosing Circle

The smallest circle containing all points. Unique, and determined by at most 3 of the points.

The key facts

  1. The minimum enclosing circle is unique.
  2. It is determined by 2 points (as a diameter) or 3 points (on its boundary).
  3. Therefore a brute-force solution exists — but Welzl’s algorithm does it in expected .

Welzl’s algorithm — expected

struct Circle { PD c; double r; };
 
bool inside(const Circle& ci, PD p) { return norm2(p - ci.c) <= ci.r * ci.r + EPS; }
Circle from2(PD a, PD b) { return {(a + b) * 0.5, abs_(a - b) / 2}; }
Circle from3(PD a, PD b, PD c) { PD o = circumcenter(a, b, c); return {o, abs_(o - a)}; }
 
Circle minEnclosingCircle(vector<PD> p) {
    shuffle(p.begin(), p.end(), rng);                 // ESSENTIAL
    Circle c{p[0], 0};
    for (int i = 0; i < (int)p.size(); i++) {
        if (inside(c, p[i])) continue;
        c = {p[i], 0};
        for (int j = 0; j < i; j++) {
            if (inside(c, p[j])) continue;
            c = from2(p[i], p[j]);
            for (int k = 0; k < j; k++) {
                if (inside(c, p[k])) continue;
                c = from3(p[i], p[j], p[k]);
            }
        }
    }
    return c;
}

Three nested loops that look — but the analysis says otherwise. (circumcenter: Triangles; degenerate when the three points are collinear, in which case the enclosing circle is determined by the two extreme points, which the algorithm’s structure already handles since that case is caught by the from2 level before three points are ever fixed together.)

The shuffle is not optional

Without it, an adversarial input (points already sorted so each new one is outside) makes the algorithm . Shuffle with a well-seeded RNG so the order cannot be predicted by whoever constructed the test data.

Tested: minEnclosingCircle checked to enclose every input point (within ) and matched in radius against a brute-force search (every pair as a diameter, every triple as a circumscribed circle, keeping the smallest that encloses all points) on random point sets up to ; also checked on adversarial sorted/collinear inputs to confirm the shuffled version still returns the correct circle (only the unshuffled version would blow up in time, not in correctness, on such inputs).

LP-type problems

Minimum enclosing circle is the archetypal LP-type problem: an optimisation over a set system with bounded combinatorial dimension (3 here), satisfying monotonicity and locality. The same framework solves:

ProblemCombinatorial dimension
Minimum enclosing circle3
Minimum enclosing ball in
Minimum enclosing ellipse5
Smallest enclosing annulus4
Linear programming in dimension
Distance between two polytopes
Largest ball inside a polytope

Recognising a problem as LP-type tells you immediately that a randomised incremental algorithm is — see Seidel’s LP for the same framework applied to linear programming, and randomised incremental Delaunay for another application of the same backward-analysis technique.

Variants

VariantMethod
Minimum enclosing rectanglerotating calipers on the hull (Toussaint) — 07-rotating-calipers
Minimum enclosing squarebinary search on the side + a sweep
Smallest circle covering of pointsmuch harder; or worse
Circle covering all with a fixed radiusis the intersection of the disks non-empty?
Largest empty circlea Voronoi vertex, hull edge, or bounding-box constraint — 20-delaunay-and-voronoi
Minimum enclosing ball in 3DWelzl with dimension 4
Circle minimising the sum of distancesthe geometric median — no closed form; use Weiszfeld’s iteration or nested ternary search

The last row is worth flagging: minimising the maximum distance gives the enclosing circle (LP-type, ), while minimising the sum gives the geometric median, a different and harder problem with no exact algorithm.

Preprocessing with the hull

Only points on the convex hull can determine the circle (an interior point is never one of the boundary-defining points, since it’s never extreme in any direction), so taking the hull first reduces to . Usually not worth it — Welzl is already linear — but useful when the hull is needed anyway.