function
getRandomInt() {
return
Math.ceil(Math.random() * 32676);
}
let R = []
function
shuffle(array) {
let currentIndex = array.length, randomIndex;
while
(currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return
array;
}
let INF = 1e18;
class Point {
constructor(a = 0, b = 0)
{
this
.X = a;
this
.Y = b;
}
};
class Circle {
constructor(p =
new
Point(0, 0), b = 0)
{
this
.C = p;
this
.R = b;
}
};
function
dist(a, b)
{
return
Math.sqrt(Math.pow(a.X - b.X, 2)
+ Math.pow(a.Y - b.Y, 2));
}
function
is_inside(c, p)
{
return
dist(c.C, p) <= c.R;
}
function
get_circle_center( bx, by,
cx, cy)
{
let B = bx * bx + by * by;
let C = cx * cx + cy * cy;
let D = bx * cy - by * cx;
return
new
Point((cy * B - by * C) / (2 * D),
(bx * C - cx * B) / (2 * D));
}
function
circle_from(A, B, C)
{
let 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
new
Circle(I, dist(I, A));
}
function
circle_from(A, B)
{
let C =
new
Point((A.X + B.X) / 2.0, (A.Y + B.Y) / 2.0);
return
new
Circle(C, dist(A, B) / 2.0);
}
function
is_valid_circle(c, P)
{
for
(
var
p
in
P)
if
(!is_inside(c, p))
return
false
;
return
true
;
}
function
min_circle_trivial(P)
{
if
(P.length == 0) {
return
new
Circle(
new
Point(0, 0), 0);
}
else
if
(P.length == 1) {
return
new
Circle(P[0], 0);
}
else
if
(P.length == 2) {
return
circle_from(P[0], P[1]);
}
for
(
var
i = 0; i < 3; i++) {
for
(
var
j = i + 1; j < 3; j++) {
let c = circle_from(P[i], P[j]);
if
(is_valid_circle(c, P))
return
c;
}
}
return
circle_from(P[0], P[1], P[2]);
}
function
welzl_helper(P, n)
{
if
(n == 0 || R.length == 3) {
return
min_circle_trivial(R);
}
let idx = getRandomInt() % n;
let p = P[idx];
let temp = P[idx]
P[idx] = P[n - 1]
P[n - 1] = temp
let d = welzl_helper(P, n - 1);
if
(is_inside(d, p)) {
return
d;
}
R.push(p);
return
welzl_helper(P, n - 1);
}
function
welzl(P)
{
let P_copy = [...P];
R = []
shuffle(P_copy);
return
welzl_helper(P_copy, P_copy.length)
}
let mec = welzl([
new
Point(0, 0),
new
Point(0, 1),
new
Point(1, 0)])
console.log(
"Center = {"
, mec.C.X,
","
, mec.C.Y
,
"} Radius ="
, mec.R);
let mec2 = welzl([
new
Point(5, -2),
new
Point(-3, -2),
new
Point(-2, 5),
new
Point(1, 6),
new
Point(0, 2)])
console.log(
"Center = {"
, mec2.C.X,
","
, mec2.C.Y
,
"} Radius ="
, mec2.R);