**Prequisites: **Equation of circle when three points on the circle are given, Minimum Enclosing Circle.

Given an array **arr[][]** containing **N** points in a 2-D plane with integer coordinates. The task is to find the centre and the radius of the minimum enclosing circle(MEC). A minimum enclosing circle is a circle in which all the points lie either inside the circle or on its boundaries.

**Examples:**

Input:arr[][] = {{0, 0}, {0, 1}, {1, 0}}

Output:Center = {0.5, 0.5}, Radius = 0.7071

Explanation:

On plotting the above circle with radius 0.707 and center (0.5, 0.5), it can be observed clearly that all the mentioned points lie either inside or on the circle.

Input:arr[][] = {{5, -2}, {-3, -2}, {-2, 5}, {1, 6}, {0, 2}}

Output:Center = {1.0, 1.0}, Radius = 5.000

**Approach:** In the previous article, a naive approach and an optimized approach by getting the convex full of the set of points first and then performing a naive approach has been discussed. Although the optimized solution would work very well for certain inputs, the worst-case time complexity after that optimization was still **O(N ^{4})**. In this article, an optimized approach has been discussed.

The idea is to use Welzl’s recursive algorithm. Using this algorithm, the MEC can be found in **O(N)**. The working of the algorithm depends on the observations and conclusions drawn from the previous article. The idea of the algorithm is to randomly remove a point from the given input set to form a circle equation. Once the equation is formed, check if the point which was removed is enclosed by the equation or not. If it doesn’t, then the point must lie on the boundary of the MEC. Therefore, this point is considered as a boundary point and the function is recursively called. The detailed working of the algorithm is as follows:

The algorithm takes a set of points **P** and a set **R** that’s initially empty and used to represent the points on the boundary of the MEC as the input.

The base case of the algorithm is when **P** becomes empty or the size of the set **R** is equal to **3**:

- If P is empty, then all the points have been processed.
- If
**|R| = 3**, then 3 points have already been found that lie on the circle boundary, and since a circle can be uniquely determined using 3 points only, the recursion can be stopped.

When the algorithm reaches the base case above, it returns the trivial solution for R, being:

- If
**|R| = 1**, we return a circle centered at R[0] with radius = 0 - If
**|R| = 2**, we return the MEC for R[0] and R[2] - If
**|R| = 3**, we return the MEC by trying the 3 pairs (R[0], R[1]), (R[0], R[2]), (R[1], R[2])- If none of these pairs is valid, we return the circle defined by the 3 points in R

If the base case is not reached yet, we do the following:

- Pick a random point p from P and remove it from P
- Call the algorithm on P and R to get circle d
- If p is enclosed by d, then we return d
- otherwise, p must lie on the boundary of the MEC
- Add p to R
- Return the output of the algorithm on P and R

Below is the implementation of the above approach:

`// C++ program to find the minimum enclosing ` `// circle for N integer points in a 2-D plane ` `#include <algorithm> ` `#include <assert.h> ` `#include <iostream> ` `#include <math.h> ` `#include <vector> ` `using` `namespace` `std; ` ` ` `// Defining infinity ` `const` `double` `INF = 1e18; ` ` ` `// Structure to represent a 2D point ` `struct` `Point { ` ` ` `double` `X, Y; ` `}; ` ` ` `// Structure to represent a 2D circle ` `struct` `Circle { ` ` ` `Point C; ` ` ` `double` `R; ` `}; ` ` ` `// Function to return the euclidean distance ` `// between two points ` `double` `dist(` `const` `Point& a, ` `const` `Point& b) ` `{ ` ` ` `return` `sqrt` `(` `pow` `(a.X - b.X, 2) ` ` ` `+ ` `pow` `(a.Y - b.Y, 2)); ` `} ` ` ` `// Function to check whether a point lies inside ` `// or on the boundaries of the circle ` `bool` `is_inside(` `const` `Circle& c, ` `const` `Point& p) ` `{ ` ` ` `return` `dist(c.C, p) <= c.R; ` `} ` ` ` `// The following two functions are used ` `// To find the equation of the circle when ` `// three points are given. ` ` ` `// Helper method to get a circle defined by 3 points ` `Point get_circle_center(` `double` `bx, ` `double` `by, ` ` ` `double` `cx, ` `double` `cy) ` `{ ` ` ` `double` `B = bx * bx + by * by; ` ` ` `double` `C = cx * cx + cy * cy; ` ` ` `double` `D = bx * cy - by * cx; ` ` ` `return` `{ (cy * B - by * C) / (2 * D), ` ` ` `(bx * C - cx * B) / (2 * D) }; ` `} ` ` ` `// Function to return a unique circle that ` `// intersects three points ` `Circle circle_from(` `const` `Point& A, ` `const` `Point& B, ` ` ` `const` `Point& C) ` `{ ` ` ` `Point I = get_circle_center(B.X - A.X, B.Y - A.Y, ` ` ` `C.X - A.X, C.Y - A.Y); ` ` ` ` ` `I.X += A.X; ` ` ` `I.Y += A.Y; ` ` ` `return` `{ I, dist(I, A) }; ` `} ` ` ` `// Function to return the smallest circle ` `// that intersects 2 points ` `Circle circle_from(` `const` `Point& A, ` `const` `Point& B) ` `{ ` ` ` `// Set the center to be the midpoint of A and B ` ` ` `Point C = { (A.X + B.X) / 2.0, (A.Y + B.Y) / 2.0 }; ` ` ` ` ` `// Set the radius to be half the distance AB ` ` ` `return` `{ C, dist(A, B) / 2.0 }; ` `} ` ` ` `// Function to check whether a circle ` `// encloses the given points ` `bool` `is_valid_circle(` `const` `Circle& c, ` ` ` `const` `vector<Point>& P) ` `{ ` ` ` ` ` `// Iterating through all the points ` ` ` `// to check whether the points ` ` ` `// lie inside the circle or not ` ` ` `for` `(` `const` `Point& p : P) ` ` ` `if` `(!is_inside(c, p)) ` ` ` `return` `false` `; ` ` ` `return` `true` `; ` `} ` ` ` `// Function to return the minimum enclosing ` `// circle for N <= 3 ` `Circle min_circle_trivial(vector<Point>& P) ` `{ ` ` ` `assert` `(P.size() <= 3); ` ` ` `if` `(P.empty()) { ` ` ` `return` `{ { 0, 0 }, 0 }; ` ` ` `} ` ` ` `else` `if` `(P.size() == 1) { ` ` ` `return` `{ P[0], 0 }; ` ` ` `} ` ` ` `else` `if` `(P.size() == 2) { ` ` ` `return` `circle_from(P[0], P[1]); ` ` ` `} ` ` ` ` ` `// To check if MEC can be determined ` ` ` `// by 2 points only ` ` ` `for` `(` `int` `i = 0; i < 3; i++) { ` ` ` `for` `(` `int` `j = i + 1; j < 3; j++) { ` ` ` ` ` `Circle c = circle_from(P[i], P[j]); ` ` ` `if` `(is_valid_circle(c, P)) ` ` ` `return` `c; ` ` ` `} ` ` ` `} ` ` ` `return` `circle_from(P[0], P[1], P[2]); ` `} ` ` ` `// Returns the MEC using Welzl's algorithm ` `// Takes a set of input points P and a set R ` `// points on the circle boundary. ` `// n represents the number of points in P ` `// that are not yet processed. ` `Circle welzl_helper(vector<Point>& P, ` ` ` `vector<Point> R, ` `int` `n) ` `{ ` ` ` `// Base case when all points processed or |R| = 3 ` ` ` `if` `(n == 0 || R.size() == 3) { ` ` ` `return` `min_circle_trivial(R); ` ` ` `} ` ` ` ` ` `// Pick a random point randomly ` ` ` `int` `idx = ` `rand` `() % n; ` ` ` `Point p = P[idx]; ` ` ` ` ` `// Put the picked point at the end of P ` ` ` `// since it's more efficient than ` ` ` `// deleting from the middle of the vector ` ` ` `swap(P[idx], P[n - 1]); ` ` ` ` ` `// Get the MEC circle d from the ` ` ` `// set of points P - {p} ` ` ` `Circle d = welzl_helper(P, R, n - 1); ` ` ` ` ` `// If d contains p, return d ` ` ` `if` `(is_inside(d, p)) { ` ` ` `return` `d; ` ` ` `} ` ` ` ` ` `// Otherwise, must be on the boundary of the MEC ` ` ` `R.push_back(p); ` ` ` ` ` `// Return the MEC for P - {p} and R U {p} ` ` ` `return` `welzl_helper(P, R, n - 1); ` `} ` ` ` `Circle welzl(` `const` `vector<Point>& P) ` `{ ` ` ` `vector<Point> P_copy = P; ` ` ` `random_shuffle(P_copy.begin(), P_copy.end()); ` ` ` `return` `welzl_helper(P_copy, {}, P_copy.size()); ` `} ` ` ` `// Driver code ` `int` `main() ` `{ ` ` ` `Circle mec = welzl({ { 0, 0 }, ` ` ` `{ 0, 1 }, ` ` ` `{ 1, 0 } }); ` ` ` `cout << ` `"Center = { "` `<< mec.C.X << ` `", "` `<< mec.C.Y ` ` ` `<< ` `" } Radius = "` `<< mec.R << endl; ` ` ` ` ` `Circle mec2 = welzl({ { 5, -2 }, ` ` ` `{ -3, -2 }, ` ` ` `{ -2, 5 }, ` ` ` `{ 1, 6 }, ` ` ` `{ 0, 2 } }); ` ` ` `cout << ` `"Center = { "` `<< mec2.C.X << ` `", "` `<< mec2.C.Y ` ` ` `<< ` `" } Radius = "` `<< mec2.R << endl; ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

**Output:**

Center = { 0.5, 0.5 } Radius = 0.707107 Center = { 1, 1 } Radius = 5

**Time Complexity:** This algorithm has an expected time and space complexity of **O(N)** where N is the number of points. The space is due to the fact recursion is being used. To understand why the time complexity is linear, we can observe the number of different states to know how many calls can happen to the recursive function. With every call, the size of **P** gets reduced by **one**. Also, the size of R can remain the same or can be increased by one. Since **|R|** cannot exceed **3**, then the number of different states would be **3N**. Therefore, this makes the time complexity to be **O(N)**.

## Recommended Posts:

- Minimum Enclosing Circle | Set 1
- Program to calculate area of inner circle which passes through center of outer circle and touches its circumference
- Equation of circle when three points on the circle are given
- Check if a circle lies inside another circle or not
- Angle subtended by the chord to center of the circle when the angle subtended by the another equal chord of a congruent circle is given
- Find area of the larger circle when radius of the smaller circle and difference in the area is given
- Area of the circle that has a square and a circle inscribed in it
- Mid-Point Circle Drawing Algorithm
- Neighbors of a point on a circle using Bresenham's algorithm
- Algorithm Library | C++ Magicians STL Algorithm
- Minimum revolutions to move center of a circle to a target
- Find minimum radius such that atleast k point lie inside the circle
- Minimum cuts required to divide the Circle into equal parts
- Minimum number of cuts required to make circle segments equal sized
- Lucky alive person in a circle | Set - 2
- Count ways to divide circle using N non-intersecting chord | Set-2
- Minimum number of subsequences required to convert one string to another using Greedy Algorithm
- Minimum Cost Maximum Flow from a Graph using Bellman Ford Algorithm
- Draw a circle without floating point arithmetic
- Non-crossing lines to connect points in a circle

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.